SpringCloudNetflix学习和实践——统一配置中心

一、了解统一配置中心

什么是统一配置中心?

SpringCloud中的统一配置中心由组件Spring Cloud Config 实现。它是一个高可用的分布式配置中心。

 

为什么需要统一配置中心?

1.方便维护:在多人协作开发的环境下,常会对同一个配置文件做修改。很容易导致别人更新代码出现配置文件的冲突,不方便维护。

2.安全与权限:项目中尤其是线上的配置,如数据库密码,是不便对普通开发人员公开的。通过统一配置中心,可以对配置和代码进行隔离。

3.更新配置需要重启:每次更新配置都需要重启服务,这样会导致服务运行效率降低。

统一配置中心都可以解决这些问题。

 

统一配置中心的架构和流程

通过config-server从远端git拉取配置到本地git给其他服务使用。

统一配置中心的两个角色

config-server : 从远程git拉取配置并且存于本地git库。当远程git连接不上,还可以使用本地git中的配置。

config-client :  由本地的服务(如订单、商品服务等)集成config-client的功能,从config-server获取其拉取到的配置。

 

二、实现配置中心服务端

1.引入依赖

新建一个名称为config-server(可自定义)的maven工程,引入作为配置中心服务端需要的依赖spring-cloud-config-server,

同时该工程还是作为一个eureka的客户端,因此还需依赖spring-cloud-starter-netflix-eureka-client:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2.开启配置中心功能

在config-server服务的启动类上使用注解@EnableDiscoveryClient 和 @EnableConfigServer分别开启eureka客户端和配置中心服务端:

@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
    }

}

3.配置远程仓库地址

尝试启动服务

可以发现控制台输出需要配置远程git地址。

因此需要新建远程git仓库:

我将订单服务的配置文件order.yml放到远程仓库中:

之后在config-server服务中配置远程仓库的地址,用户名、密码、要配置文件拉取到的本地文件夹(会自动初始化本地git库):

 

之后启动config-server服务,

console中打印了config-server提供的访问规则,根据访问规则可以直接在浏览器查看和访问配置文件。

规则说明:

{/name}指服务名

{profiles}指环境

{label}指git分支

例如在远程新建分支“temp”,在“temp”分支上新建了order-dev.yml,

那么访问规则就是:

{本机ip:config-server服务端口}/{分支名}/{服务名-环境}.yml

http://127.0.0.1:8080/temp/order-dev.yml

要注意的是,即使远程仓库中是order.yml,没有带有环境名,也需加上任意字符串才可访问,

http://127.0.0.1:8080/order-a.yml


查看确实自动clone了git库到本地及拉取了远端配置文件:

 

三、实现配置中心客户端

以order服务举例,实现配置中心客户端的功能。

首先将准备好的order.dev.yml存入远程git库:

在order服务中引入配置中心客户端需要的依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>

因为要使用configserver从远程拉取的配置order-yml,所以本地的application.yml中不再需要保留数据源、eureka相关配置,

本地application.yml仍然需保留,但是只需配置“ 服务名称、开启配置中心、配置中心服务端的服务名、配置文件环境 ” 用来向config-server获取配置:

在启动order服务后 config-client端将会根据服务名order和环境后缀dev到config-server端找寻配置文件order.dev.yml。

尝试启动order服务:

可以发现启动失败,找不到数据源信息。

这是因为服务启动就会直接在本地的application.yml中找寻数据源配置信息。

解决办法:可以将本地的application.yml改名为bootstrap.yml,基于springboot配置文件加载规则,bootstrap.yml中的内容会优先加载,之后再去config-server获取到远端配置文件内容后再加载远程相关配置中如数据源等信息。

为了查看其中的配置内容是否确实获取到了,再次启动之前,编写一个测试接口:

environment是我在远端order-dev.yml中的一个配置项,若成功获取配置,则此接口可以返回envir的内容。

成功启动后调用接口,可以正常返回该配置内容:

在console中也可以看到启动服务时获取配置文件的相关日志:

 

四、使用springcloudconfig要注意的一些问题

1、高可用的问题

配置中心客户端的功能虽然实现了。但是只是单台config-server显然无法是满足高可用的要求。

在生产环境服务端肯定是需要多启动几台config-server实例的。

2、修改远程eureka配置引发的问题

在前文中,我启动了eureka-server的实例端口是8761的默认端口。

假如把eureka-server的启动端口改为8762

config-server中连接eureka相应的改为8762

远程的配置文件order-dev中也相应的进行修改。

启动eureka-server、config-server,config-server正常启动,注册成功了:

但是启动order服务时,发现报错,而且连接config-server获取配置的url是错误的,我config-server端口是8080,为什么会这样?

config-client连接config-server的默认端口是8888,我在order服务中如前文的配置,基于eureka的服务发现,应该用8080连接ureka。为什么会走默认端口,导致报错?

问题原因:

order启动的第一件事是先去eureka注册中心找config-server的服务地址,才能通过config-server获取远程配置,但我现在还没有获取到远程git上的eureka配置信息,又如何连接eureka-server呢?于是order服务就会走默认的8761连接eureka-server。

原本eureka是使用8761启动,order服务第一次因为没有配置,会通过默认访问eureka-server端口8761,可以访问到eureka-server,从eureka-server获得了config-server的正确地址,所以获取配置时走config-server的8080端口,一切正常。

现在eureka启动端口改成8762,order服务因为没有eureka配置,仍然走8761访问eureka-server,就无法连接到eureka,也就无法获取到注册在eureka上的config-server地址,只能走默认连接config-server的8888端口,导致访问了错误的8888去连接config-server。

解决: 所以对于eureka-server的访问配置信息,就不要配置在远程仓库了,将远程仓库上order-dev.yml中eureka配置信息剪到本地的bootstrap.yml中。让服务启动时能正确访问eureka-server。

3. 删除远程eureka配置信息未生效

为了解决问题2,我已经将远程仓库中order-dev.yml文件里的eureka相关配置移除,将这些信息配置到本地的order服务中。

但是我多次刷新config-server从远程git拉取到的配置内容,发现配置文件中该eureka相关内容是还是存在:

为什么修改没有生效?

再吃刷新请求配合文件,可以发现拉取了两个配置文件。

问题产生的原因:

之前在实现config-server的过程中,有说到拉取配置文件的url规则,http://localhost:8080/order-dev.yml这个路径其实也是符合拉取order.yml的,因此会将order-dev.yml和order.yml都进行拉取并且合并,而在order.yml中其实还存在eureka的配置信息没有删除,会被合并。因此出现了删除oder-dev.yml中内容无效的现象。

解决方法:

那么是否把order.yml直接删除最好呢?

并不是,把其中需要删掉的配置内容删去即可,order.yml可以保留。

既然order.yml不管在什么拉取任何环境的配置文件时都会被一同拉取,不如就在需要时将各个环境都需要的公共的配置定义在里面。这样也提高了配置的复用性。

 

五、SpringCloudBus实现动态刷新配置

前面实现了config-server和order服务的config-client,但是修改配置以后,还需要重启order服务,

还没有实现修改配置无需重启服务的功能。

要实现服务运行时动态的刷新配置,就需要引入一个新的springcloud组件:SpringCloudBus ;

 

配置的动态刷新的实现原理

order服务在启动后,访问config-server获取配置,但在修改了远端配置后,order服务是不知道的。

因此实现动态刷新配置的关键在于如何在修改了远端配置后,config-server能够通知到order服务。

怎么通知呢,通知消息的承载就需要载体,也就是消息队列,比如RabbitMQ。

这里要操作消息队列就需要SpringCloudBus。

 

configserver和order服务通过消息队列来传递信息,config-server在使用了SpringCloud Bus后会对外提供一个接口,叫做

/bus-refresh。访问这个接口,config-server就会把更新配置的信息发送到MQ中。

我们希望的是远端git上修改配置后就能够访问这个接口,因此这个接口自然由git来访问最好。在如Github之类的git服务器基本都有提供WebHook的功能,只要把接口配置进去就可以。当发生修改时,Github就会对WebHook中的配置的接口进行调用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章