Spring Cloud Config配置服务及那些你不知道的坑

这篇具有很好参考价值的文章主要介绍了Spring Cloud Config配置服务及那些你不知道的坑。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、为什么选择Spring Cloud Config

1.1 集中式管理

1.2 动态修改配置

2、Spring Cloud Config 简介

3、服务端配置

3.1 添加依赖

3.2 开启服务注册

3.3 添加YML配置

3.4 创建远程分支及Profile配置文件

3.5 启动并测试服务

4、客户端配置

4.1 添加依赖

4.2 开启服务注册

4.3 添加YML配置

4.4 启动并测试服务

5、原因分析

5.1 定位问题原因

5.2 定位问题2分析过程

5.3 定位问题1分析过程

5.3.1 逆向排查

5.3.2 正向跟踪


1、为什么选择Spring Cloud Config

如何将配置信息直接写在本地yml配置文件存在哪些痛点呢?

如果多个微服务可能使用相同的配置信息,假设有50个微服务,如果配置需要修改配置文件,就意味着我们需要修改50个微服务的yml文件,极其浪费时间。配置信息修改后,必须重启服务才能生效。

相比较同类产品,SpringCloudConfig最大的优势是和Spring无缝集成,支持Spring里面Environment和PropertySource的接口,对于已有的Spring应用程序的迁移成本非常低,在配置获取的接口上是完全一致,结合SpringBoot可使你的项目有更加统一的标准(包括依赖版本和约束规范),避免了应为集成不同开软件源造成的依赖版本冲突。

而Spring Cloud Config解决了这两个痛点:

1.1 集中式管理

在开发中多个微服务可能使用相同的配置,假设有50个微服务,如果配置需要修改配置文件,就意味着我们需要修改50个微服务的yml文件。使用配置中心后,就可以做到一处修改,处处修改。

1.2 动态修改配置

使用配置中心,配合actuator可以实现配置的动态修改,无需重启服务

2、Spring Cloud Config 简介

SpringCloudConfig就是我们通常意义上的配置中心,把应用原本放在本地文件的配置抽取出来放在中心服务器,从而能够提供更好的管理、发布能力。SpringCloudConfig分服务端和客户端,服务端负责将git svn中存储的配置文件发布成REST接口,客户端可以从服务端REST接口获取配置。但客户端并不能主动感知到配置的变化,从而主动去获取新的配置,这需要每个客户端通过POST方法触发各自的/refresh。

SpringCloudBus通过一个轻量级消息代理连接分布式系统的节点。这可以用于广播状态更改(如配置更改)或其他管理指令。SpringCloudBus提供了通过POST方法访问的endpoint/bus/refresh,这个接口通常由git的钩子功能调用,用以通知各个SpringCloudConfig的客户端去服务端更新配置。

注意:这是工作的流程图,实际的部署中SpringCloudBus并不是一个独立存在的服务,这里单列出来是为了能清晰的显示出工作流程。

下图是SpringCloudConfig结合SpringCloudBus实现分布式配置的工作流:

Spring Cloud Config配置服务及那些你不知道的坑

 

简单说明一下流程:

1)把配置文件放在Git Repository中。

2)Config Server从Git repository中读取配置信息。

3)其他客户端再从Config Server中加载配置文件

3、服务端配置

紧接上一篇内容代码示例,创建一个新的module. 命名为:springcloud-config-server。

Spring Cloud Config配置服务及那些你不知道的坑

 

3.1 添加依赖

在springcloud-config-server pom.xml中添加config-server依赖。如下,

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-config-server</artifactId>

</dependency>

Spring Cloud Config配置服务及那些你不知道的坑 

3.2 开启服务注册

新建启动类SpringCloudConfigServerApp,并添加@EnableConfigServer,表示开启 SpringCloudConfig配置。

代码示例如下,

package com.xintu.springcloud;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.config.server.EnableConfigServer;



/**

 * @author XinTu

 * @classname SpringCloudConfigServerApp

 * @description TODO

 * @date 2023年03月23日 14:02

 */



@SpringBootApplication

@EnableConfigServer

public class SpringCloudConfigServerApp {

    public static void main(String[] args) {

        SpringApplication.run(SpringCloudConfigServerApp.class, args);

    }

}

3.3 添加YML配置

新增配置文件 application.yml。配置文件添加内容如下,

# 服务端口

server:

  port: 8086



#指定应用名称

spring:

  application:

    name: config-server

  cloud:

    config:

      label: master #配置git仓库分支

      server:

        git:

          uri: https://gitee.com/lwbook/spring-cloud-config.git #配置git仓库地址

          search-paths: spring-cloud-config #配置仓库路径

          #username:  git_username #访问git仓库的用户名,公开仓库不配置用户名

          #password: git_password #访问git仓库的用户密码,公开仓库不配置密码

3.4 创建远程分支及Profile配置文件

1) 远程配置仓库及文件根据自己公司环境自行创建。

这里老王提供一个自己创建的公共Git地址。https://gitee.com/lwbook/spring-cloud-config.git。

该仓库下新建了一个xintu-config文件夹。

在xintu-config 文件夹下分别创建3个文件。

注意:文件命名规格:{项目名}-{配置环境版本}.yml。比如application-dev.yml,表示的是application项目的开发环境配置。

📕开发环境配置: application-dev.yml

添加内容:

env: dev

test: 1

📕测试环境配置:application-test.yml

添加内容:

env: test

test: 2

📕预发环境配置:application-pre.yml

添加内容:

env: pre

test: 3

Spring Cloud Config配置服务及那些你不知道的坑

 3.5 启动并测试服务

启动程序 SpringCloudConfigServerApp类后,输入http://localhost:8086/application/dev访问 springcloud-config-server服务。出现如下界面,则表示配置服务中心可以从远程程序获取配置信息。

Spring Cloud Config配置服务及那些你不知道的坑

 

{"name":"application","profiles":["dev"],"label":null,"version":"6abb9b9f47dedfe76592d3496a057dce4f74a9fe","state":null,"propertySources":[{"name":"https://gitee.com/lwbook/spring-cloud-config.git/xintu-config/application-dev.yml","source":{"env":"dev","test":1}}]}

看下后台日志打印,

Spring Cloud Config配置服务及那些你不知道的坑

 

至此,COnfig服务端配置完成。

4、客户端配置

创建一个新的module. 命名为:springcloud-config-client。

Spring Cloud Config配置服务及那些你不知道的坑

 

4.1 添加依赖

在springcloud-config-client pom.xml中添加config-client依赖。如下,

<!-- config client-->

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-config-client</artifactId>

</dependency>

<!-- 添加web 用于获取config数据测试 -->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

</dependency>

Spring Cloud Config配置服务及那些你不知道的坑

 

4.2 开启服务注册

新建启动类SpringCloudConfigClientApp, 代码示例如下,


package com.xintu.springcloud;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;



/**

 * @author XinTu

 * @classname SpringCloudConfigClientApp

 * @description TODO

 * @date 2023年03月23日 14:02

 */



@SpringBootApplication

public class SpringCloudConfigClientApp {

    public static void main(String[] args) {

        SpringApplication.run(SpringCloudConfigClientApp.class, args);

    }

}

新建一个测试controller类,在程序的启动类 ConfigClientController 通过 @Value 获取服务端的 env和 test值的内容。

代码示例:

package com.xintu.springcloud.controller;



import org.springframework.beans.factory.annotation.Value;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;



/**

 * @author XinTu

 * @classname ConfigClientController

 * @description TODO

 * @date 2023年03月23日 14:20

 */

@RestController

public class ConfigClientController {

    @Value("${env}")

    String env;



    @Value("${test}")

    String test;



    @RequestMapping("/")

    public String test() {

        return String.format("env=%s;test=%s", env, test);

    }

}

4.3 添加YML配置

添加配置文件 application.yml。

# 服务注册中心 (单节点)

server:

  port: 8087



#指定应用名称

spring:

  application:

    name: config-client

  cloud:

    config:

      label: master #配置git仓库分支

      profile: dev #开发环境配置文件

      uri: http://localhost:8086/ #指明配置服务中心的网址



#配置默认值,否则启动时会报错;配置中心有则用配置中心

env: prod

test: 4

4.4 启动并测试服务

启动程序 SpringCloudConfigClientApp类后,发现如下异常信息。

Spring Cloud Config配置服务及那些你不知道的坑

 

1)看第一条错误信息,加载的地址端口不是8086,而是8888.

2)看第二条错误信息,虽然端口没变,但是application、profile和lable变成了我们自己配置的内容。

Spring Cloud Config配置服务及那些你不知道的坑

 

我们再访问页面:http://localhost:8087/test

Spring Cloud Config配置服务及那些你不知道的坑

 

* 期望的是env=dev,test=3.而返回的是prod和4.说明我们的git配置没获取成功。

先说解决方案:

方案一:把application.yml换为bootstrap.yml文件即可。

方案二:把config serverz的端口改为8888,当然这种只限于localhost模式,跨服务器是行不通的。

问题原因分析见第5节。

5、原因分析

网上有类似的问题的回答,建议把application.yml调整为bootstrap.yml,修改后确实生效了。但这个是真的的答案吗?能解释问题1,但是无法解释问题2。所以,我们还需要继续查找问题根因。

先看官网:https://cloud.spring.io/spring-cloud-static/spring-cloud.html。

Spring Cloud Config配置服务及那些你不知道的坑

大致意思就是bootstrap的配置会优先application。但官网只解释了用bootstrap替换application的问题。但从前面的异常我们发现,虽然uri依然采用的是默认值,但是application、profile和lable这三个值被我们自己定义的覆盖了。很显然依然解释不清楚问题2。

难道是Spring Cloud的官网解释的有问题?随着老王的思路一步一步排查

5.1 定位问题原因

找到打印异常信息的类,

c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://localhost:8888/. Will be trying the next url if available

Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/application/dev/master": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect

发现时Spring Cloud Config自身类有一个uri默认值,也就是我们看到的ConfigClientProperties private String[] uri = { "http://localhost:8888" }。它使用了默认的值。

Spring Cloud Config配置服务及那些你不知道的坑

 那可以推断出项目中application.yml没有把uri值覆盖掉,而且除application.yml外,其他地方也没有单独配置uri的值。但是name,lable和profile是生效了。所以这么看并不是application.yml没有生效啊?

5.2 定位问题2分析过程

那究竟时怎么覆盖的呢?我们可以从发送http请求出问题的地方入手。

Spring Cloud Config配置服务及那些你不知道的坑

 

调用的是org.springframework.cloud.config.client.ConfigServicePropertySourceLocator#getRemoteEnvironment方法。那需要排查前面是否有单独处理三个值的地方。我们会发现有一个方法:

Spring Cloud Config配置服务及那些你不知道的坑

 

ConfigClientProperties properties = this.defaultProperties.override(environment); 这个地方有一个覆盖值的方法,进到方法内部。会发现这三个值被重新覆盖了。

Spring Cloud Config配置服务及那些你不知道的坑

 

那这就奇怪了,为什么要覆盖?被谁覆盖了?再解析属性的地方打断点,我们继续调试跟踪。

发现是从application.yml中获取的值。

Spring Cloud Config配置服务及那些你不知道的坑

 那这就解释了为什么另外3个值会被覆盖的原因了。

5.3 定位问题1分析过程

解决了前面三个属性值覆盖问题,现在我们回头看uri的值为什么没被覆盖掉。

5.3.1 逆向排查

首先,我们需要看哪儿调用了这个类,发现这个类构造函数(仅有一个构造方法),

Spring Cloud Config配置服务及那些你不知道的坑

 

org.springframework.cloud.config.client.ConfigServicePropertySourceLocator#ConfigServicePropertySourceLocator//构造函数。那此时我们就需要看谁调用了这个构造函数。

Spring Cloud Config配置服务及那些你不知道的坑

org.springframework.cloud.config.client.ConfigServiceBootstrapConfiguration#configServicePropertySource这个方法。

继续回退,看是谁调用了configServicePropertySource这个方法。

Spring Cloud Config配置服务及那些你不知道的坑

结果没有地方调用。而且构造函数也没有被调用。那就看类在那些位置被加载了。

Spring Cloud Config配置服务及那些你不知道的坑

此时,我们注意到有一个spring.factories文件。这个回到了我们熟悉的spring类扫描机制。我们看到,这个类被spring cloud的四个文件所引用。先看第一个文件,spring.factories。

Spring Cloud Config配置服务及那些你不知道的坑

 

我们知道,有时候希望一些第三方包被Spring管理,但是不想被Spring Boot扫描到。通常我们会采用注解进行实例化,另外一种是使用spring.factories机制。那这里的spring.factories就是通过这种方式管理Spring Cloud的包的。继续跟踪代码spring.factories文件。

这个就要看,什么时候加载并注入的spring cloud类。那我们就要从头开始跟踪代码。

5.3.2 正向跟踪

1)定位监听

我们从main函数开始跟踪,进入到我们所熟悉的run这个方法。

org.springframework.boot.SpringApplication#run(java.lang.String...)

Spring Cloud Config配置服务及那些你不知道的坑

 

很关键的两行代码,

// 关键点1:扫描所有包下实现了ApplicationListener接口的实现类,提前注入依赖参数。

SpringApplicationRunListeners listeners = getRunListeners(args);

listeners.starting(); //开启事件监听

try {

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); //关键点2: 准备配置信息,这里是加载yml和properties的关键方法

}

Spring Cloud Config配置服务及那些你不知道的坑

 

此时,我们继续看BootstrapApplicationListener这个类是怎么样的处理机制?抓入口,看onApplicationEvent(ApplicationEnvironmentPreparedEvent event) 这个方法。这个是Spring Boot的上下文加载监听事件。

打断点继续跟踪。发现了一个很关键的信息,就是spring.config.name=bootstrap的信息。这个配置会影响后面如何加载配置文件的流程。

Spring Cloud Config配置服务及那些你不知道的坑

 

BootstrapApplicationListener加载完后,我们继续往后看。前面提到了两个关键点,第一个知道了其作用,那第二个是怎么触发的呢?继续看监听器列表,注意这个ConfigFileApplicationListener监听器,就是接下来加载配置文件(第二关键点的位置)。

2)定位配置

Spring Cloud Config配置服务及那些你不知道的坑

 

当执行到org.springframework.boot.context.config.ConfigFileApplicationListener#onApplicationEvent时,

Spring Cloud Config配置服务及那些你不知道的坑

此处时根据不同事件,执行不同的处理逻辑。

Spring Cloud Config配置服务及那些你不知道的坑

 

此处的event为ApplicationEnvironmentPreparedEvent,会进入到org.springframework.boot.context.config.ConfigFileApplicationListener#onApplicationEnvironmentPreparedEvent方法。

Spring Cloud Config配置服务及那些你不知道的坑

注意这句话,postProcessors.add(this); 表示将当前ConfigFileApplicationListener加到postProcess中。我们看org.springframework.boot.context.config.ConfigFileApplicationListener#postProcessEnvironment方法中调用了addPropertySources, 而addPropertySources中才是真正去调用加载配置文件的方法load()。

继续看load方法。

Spring Cloud Config配置服务及那些你不知道的坑

 

直接进入load的重载方法中,

Spring Cloud Config配置服务及那些你不知道的坑

 这个方法就是我们前面让大家记住的spring.config.name=bootstrap, 这个方法会影响加载资源文件的先后顺序。

Spring Cloud Config配置服务及那些你不知道的坑

此处逻辑为,如果配置了spring.config.name,就执行自己配置的。

Spring Cloud Config配置服务及那些你不知道的坑

 如果没有配置,则执行默认的,及application。

Spring Cloud Config配置服务及那些你不知道的坑

 而在我们的BootstrapApplicationListener中,已经写死了spring.config.name=bootstrap,所以此时走名称为bootstrap的配置文件,继续跟踪。

Spring Cloud Config配置服务及那些你不知道的坑

 

我们debug也发现,这个名称就是bootstrap。也就是会扫描这几个路径下的boorstrap.yml或bootstrap.properties文件。

Spring Cloud Config配置服务及那些你不知道的坑

Spring Cloud Config配置服务及那些你不知道的坑 

 扫描路径,

Spring Cloud Config配置服务及那些你不知道的坑

 综上,我们知道了,SpringCloud会先加载名为bootstrap的配置文件。

3)定位注入

前面我们知道了spring cloud会加载名为bootstrap的问题,那再什么位置给ConfigClientProperties进行赋值处理的呢?这个就回到了Spring注入类是,需要将相关依赖都注入进来。

Spring Cloud Config配置服务及那些你不知道的坑

 所以在org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration注入时,会把所依赖的ConfigClientProperties类等也一起加载进来。

Spring Cloud Config配置服务及那些你不知道的坑

 

在调用栈中,我们看到,org.springframework.cloud.config.client.ConfigClientProperties是被当作参数初始化进来的。

Spring Cloud Config配置服务及那些你不知道的坑

 Spring Cloud Config配置服务及那些你不知道的坑

 综上,我们知道了Spring Cloud会优先加载bootstrap.yml或bootstrap.properties文件。那Spring Cloud为什么要这么做呢?

从config中以及参考官网的一些说法,我们能看到,bootstrap.yml可以理解成优先级别高的一些参数配置,不想被其他配置覆盖。而application是偏应用层面的,可能会因不同环境而不同。从Spring Cloud的设计者角度考虑,认为像git这种配置,应该是固定不变的。

以上!文章来源地址https://www.toymoban.com/news/detail-446126.html

到了这里,关于Spring Cloud Config配置服务及那些你不知道的坑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring Cloud 】进阶之Config配置中心

    目录 config大致的一个思路: 二,前期准备 2.1导入依赖 2.2编写bootstrop.yml: 三,编写Controller类 3.1获取单个配置类信息 3.2获取多个配置类信息                                   🎉🎉欢迎来到我的CSDN主页!🎉🎉                         🏅我是平顶山大师,一个在C

    2024年01月17日
    浏览(39)
  • 在Spring Cloud Config Github配置中心

    关于Spring Cloud系列我们其实讲解了很多,但是这里我们介绍一下Spring Cloud Config,它是一个解决分布式系统的配置管理方案,他包含了Client 和 Server 两个部分,server提供配置文件的存储,以接口的方式将配置文件内容提供出去,Client通过接口获取相关数据,并依据数据初始化自

    2024年01月19日
    浏览(43)
  • Spring Cloud之Config分布式配置应⽤

    . 右键⽗⼯程【 yx-parent 】选择【 New 】 - 【 Module 】选项,然后选择创建【 Maven 】类型项⽬(不勾选模 板),将项⽬名称设置为【yx-cloud-config 】。   在 yx-cloud-config ⼯程的 pom.xml⽂件中引⼊以下依赖坐标(需要将⾃⼰注册到 Eureka )。 在 com.yx.config 包下创建 ConfigApplication 启

    2024年02月15日
    浏览(47)
  • 第十二章 Spring Cloud Config 统一配置中心详解

    目录 一、配置问题分析及解决方案 1、问题分析 2、解决方案 二、Spring Cloud Config 介绍 1、Spring Cloud Config特性 2、Spring Cloud Config作用     3、Spring Cloud Config 组件    统一配置中心服务端    统一配置中心客户端 4、Spring Cloud Config 工作流程 三、 配置中心使用 1 搭建远程 git

    2024年02月16日
    浏览(40)
  • Spring Cloud【Config客户端配置与测试、Config客户端之动态刷新 、什么是Spring Cloud Bus、Docker安装RabbitMQ】(十)

      目录 分布式配置中心_Config客户端配置与测试 为什么要引入bootstrap 

    2024年02月15日
    浏览(43)
  • 【SpringCloudNetflix】一图理解Spring Cloud Netflix解决了那些微服务问题?

    注册中心:Eureka 负载均衡:Ribbon、Feign 服务熔断:Hystrix 服务降级:Hystrix 服务监控:Hystrix Dashboard 路由网关:Zuul 配置中心:Config git资源仓库:Spring Cloud Netflix 参考文章:https://zhuanlan.zhihu.com/p/353806201 坑:依赖版本对应问题 不断学习补充中,如理解有偏差的点,烦请指教!

    2024年02月08日
    浏览(86)
  • 【配置nacos】使用application.yml配置文件来配置spring-cloud-starter-alibaba-nacos-config

    1.首先修改pom.xml文件,引入spring-cloud-starter-alibaba-nacos-config依赖 2.在应用的 /src/main/resources/application.yml 配置文件中配置 Nacos Config 元数据 这里注意一下, 官方文档上面给的使用bootstrap.properties 来进行配置的, 我是使用的application.yml 来进行配置的。 【出现的问题以及解决】

    2024年01月24日
    浏览(49)
  • 解决 Spring Cloud 2021.0.5 版本,使用 nacos 做配置中心,报 No spring.config.import property has been defined 的问题

    报错信息如下 Description: No spring.config.import property has been defined Spring 官方给出的解决方案如下 Add a spring.config.import=nacos: property to your configuration. If configuration is not required add spring.config.import=optional:nacos: instead. To disable this check, set spring.cloud.nacos.config.import-check.enabled=false. 这里只

    2024年02月11日
    浏览(58)
  • 聊聊开发中常见几种Spring Cloud Config 的配置文件bootstrap.yml、bootstrap-dev.yml 和 bootstrap-prod.yml

    bootstrap.yml、bootstrap-dev.yml 和 bootstrap-prod.yml 是 Spring Cloud Config 的配置文件,用于获取配置信息并将其应用到应用程序中。它们之间的区别在于它们被加载的顺序和用途,主要用于不同环境下的配置管理。 1. bootstrap.yml       bootstrap.yml 是 Spring Cloud Config 中用于获取外部配置

    2024年02月09日
    浏览(39)
  • Spring Cloud Config: 了解、原理和使用

    Spring Cloud Config 是 Spring Cloud 生态系统中的一个重要组件,它提供了一种分布式配置管理的解决方案,能够集中管理应用程序的配置,支持多种后端存储,如 Git、SVN、本地文件系统、Vault 等。在本文中,我们将介绍 Spring Cloud Config 的概念、原理和使用方法,并提供一些代码示

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包