Spring Cloud Config for configuration center, to see which one is enough

Spring Cloud Spring Cloud Config is a configuration of the oldest family center, although later released Consul can replace the function of distribution center, but still suitable for Spring Cloud Config project, the function can be realized by a simple configuration.

A profile is familiar to us, especially Spring Boot project, in addition to the introduction of the corresponding maven package, the rest of the work is to improve the configuration files, such as mysql, redis, security related configuration. In addition to the basic configuration items running, there is some configuration with our business relationship, for example, seven cattle storage, SMS related to mail-related, or switch on some business.

For some simple projects, we are generally directly related to the configuration in a separate configuration file, appear to properties or yml format, the way life really is more directly into application.properties or application.yml in. But this way there is a significant problem, that is, when modifying the configuration, you must restart the service, otherwise the configuration can not take effect.

There are a number of more use of open source configuration center, such as Ctrip Apollo, ants gold dress disconf, etc., compared to Spring Cloud Config, the configuration of these centers more powerful. Interested can be used to give it a try.

Next , we began to integrate in Spring Boot Spring Cloud Config project and to github as a configuration memory. Git addition, the database can also be used, the svn, stored as local files. Config mainly about the use of the following three terms.

1. Basic configuration of the center (the Eureka not integrated);

2. The binding version of the configuration Eureka center;

3. To achieve configuration automatically refresh;

To achieve the simplest configuration center

The simplest configuration center, is to start a service as a service side, after each need to get the configuration of service as a client to obtain the service side configuration.

First established in the configuration file in github

Warehouse address created for me: distribution center warehouse

Directory structure is as follows:

Content profile substantially as follows, for distinguishing, slightly different.

data:
  env: config-eureka-dev
  user:
    username: eureka-client-user
    password: 1291029102

Note the name of the file is not played by chaos, such as the above config-single-client-dev.yml and config-single-client-prod.yml two different versions of the same project, the project name for the config-single-client , corresponding to a development version and one for the official version. config-eureka-client-dev.yml and config-eureka-client-prod.yml is another project, the project name is config-eureka-client.

Create the configuration center server

1, the new Spring Boot project, introduced config-server and starter-web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- spring cloud config 服务端包 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

2, Configuration config configuration items related

bootstrap.yml file

spring:
  application:
    name: config-single-server  # 应用名称
  cloud:
     config:
        server:
          git:
            uri: https://github.com/huzhicheng/config-only-a-demo #配置文件所在仓库
            username: github 登录账号
            password: github 登录密码
            default-label: master #配置文件分支
            search-paths: config  #配置文件所在根目录

application.yml

server:
  port: 3301

3, associated with an increased annotation on Application startup class @EnableConfigServer

@SpringBootApplication
@EnableConfigServer
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Start the service, the next test.

Spring Cloud Config has its own set of access rules, we adopted this set of rules can be accessed directly in the browser.

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

{Application} is the application name, corresponds to the profile up, is to configure the name of the file, for example configuration file created above me.

Version {profile} is the profile of our project development version, version of the test environment, production version, corresponds to the configuration file is up to application- {profile} .yml distinction, such as application-dev.yml, application- sit.yml, application-prod.yml.

{Label} represent git branch, the default is the master branch, branch if the project is to make distinction is possible, it can control access to different configuration files through a different label.

5 rules above, we only look at the first three, because I have here are yml profile format. According to these three rules, we can view the contents of the configuration file at the following address:

http://localhost:3301/config-single-client/dev/master

http://localhost:3301/config-single-client/prod

http://localhost:3301/config-single-client-dev.yml

http://localhost:3301/config-single-client-prod.yml

http://localhost:3301/master/config-single-client-prod.yml

By accessing the above address, if data can be returned to normal, then configure the server center everything is normal.

Create the configuration center client, using the configuration

Configuration Center server Well, configuration data is ready, the next, it is necessary to use it in our project.

1, reference related maven package.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- spring cloud config 客户端包 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2, initial configuration file

bootstrap.yml

spring:
  profiles:
    active: dev

---
spring:
  profiles: prod
  application:
    name: config-single-client
  cloud:
     config:
       uri: http://localhost:3301
       label: master
       profile: prod


---
spring:
  profiles: dev
  application:
    name: config-single-client
  cloud:
     config:
       uri: http://localhost:3301
       label: master
       profile: dev

Configured with two versions of the configuration, and set the version currently used by spring.profiles.active, e.g. dev version used in the present embodiment.

application.yml

server:
  port: 3302
management:
  endpoint:
    shutdown:
      enabled: false
  endpoints:
    web:
      exposure:
        include: "*"

data:
  env: NaN
  user:
    username: NaN
    password: NaN

Where management is about the actuator associated with the next automatic refresh configuration when you need it.

data part is when you can not read the configuration of the distribution center, with this configuration, so the project can not start.

3, to read the contents of the configuration of the center, adding related class configuration, Spring Cloud Config reads the configuration center and read the contents of the way local profile configuration is exactly the same. Can be obtained by @Value or @ConfigurationProperties.

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

4. To read the contents of the configuration of the center, adding related class configuration, Spring Cloud Config reads the configuration center and read the contents of the way local profile configuration is exactly the same. Can be obtained by @Value or @ConfigurationProperties.

Use @Value way:

@Data
@Component
public class GitConfig {

    @Value("${data.env}")
    private String env;

    @Value("${data.user.username}")
    private String username;

    @Value("${data.user.password}")
    private String password;

}

Use @ConfigurationProperties way:

@Component
@Data
@ConfigurationProperties(prefix = "data")
public class GitAutoRefreshConfig {

    public static class UserInfo {
        private String username;

        private String password;

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }

    private String env;

    private UserInfo user;
}

4, an additional test used to configure RESTController

@RestController
public class GitController {

    @Autowired
    private GitConfig gitConfig;

    @Autowired
    private GitAutoRefreshConfig gitAutoRefreshConfig;

    @GetMapping(value = "show")
    public Object show(){
        return gitConfig;
    }

    @GetMapping(value = "autoShow")
    public Object autoShow(){
        return gitAutoRefreshConfig;
    }
}

5, project startup class

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

Start the project, access RESTful interface

http: // localhost: 3302 / show, results are as follows:

{
  "env": "localhost-dev-edit",
  "username": "fengzheng-dev",
  "password": "password-dev"
}

http: // localhost: 3302 / autoShow, results are as follows:

{
  "env": "localhost-dev-edit",
  "user": {
      "username": "fengzheng-dev",
      "password": "password-dev"
    }
}

Automatic refresh

This mechanism Spring Cloud Config loaded at boot configuration item content, it leads to the existence of a defect, the modified configuration file contents, is not automatically refreshed. For example, we project above, when the service has been launched, to modify the contents of the configuration file on github, this time, refresh the page again, I'm sorry, old configuration or content, the new content will not take the initiative to refresh over.
However, you can not always modify the configuration after restarting the service it. If that's the case, or do not use it for good, the direct use of local profile would not be faster.

It provides a refresh mechanism, but we need to take the initiative triggered. That is @RefreshScope notes combined with actuator, pay attention to the introduction of spring-boot-starter-actuator package.

1, increase the actuator configured in config client-side configuration, you probably noticed above.

management:
  endpoint:
    shutdown:
      enabled: false
  endpoints:
    web:
      exposure:
        include: "*"

In fact, here is the main use of this interface refresh

2, an increase in the need to read the configuration of class @RefreshScope comments, we are used to configure controller, so add in the controller.

@RestController
@RefreshScope
public class GitController {

    @Autowired
    private GitConfig gitConfig;

    @Autowired
    private GitAutoRefreshConfig gitAutoRefreshConfig;

    @GetMapping(value = "show")
    public Object show(){
        return gitConfig;
    }

    @GetMapping(value = "autoShow")
    public Object autoShow(){
        return gitAutoRefreshConfig;
    }
}

Note that the above is done at the client side modifications.

After that, restart the client end, after the restart, we modify the contents of the configuration file on github, and commit the changes, refresh the page again, no response. no problem.

Next, we send a POST request to http: // localhost: 3302 / actuator / refresh this interface, you can use tools like the postman, this interface is used to trigger load the new configuration, returned as follows:

[
    "config.client.version",
    "data.env"
]

After that, once again access RESTful interface, http: // localhost: 3302 / autoShow this interface to obtain the data is up to date, indicating refresh mechanism worked.

The http: // localhost: 3302 / show acquire or old data, which is achieved @Value annotations are, therefore, we do not use this approach in the project to load the configuration.

Configuring Webhook in the github

After this end of it, and no, we can not always change the configuration, use postman access at an interface refresh it, or it is not convenient enough. github provides a webhook way, when there are changes to the code, we will call the address set to achieve the aim we want to achieve.

1, into the github repository configuration page, select Webhooks, and click add webhook;

2, then fill in the callback address, that is, the above-mentioned actuator / refresh this address, but must ensure that the address can be accessed to github. If the network is no other way. This is only a demonstration project will be within the general company has its own code management tools, such as self-built gitlab, gitlab there webhook function, so that you can call to an address within the network.

Use Spring Cloud Bus automatically refresh multiple end

Spring Cloud Bus node with a lightweight message broker link distributed systems. This can be used to change the status of a broadcast (e.g., configuration change) command, or other management. A key idea is that the distributed actuator Bus is like an extended Spring Boot applications, but can also be used as a communication channel between applications.

- Spring Cloud Bus official explanation

如果只有一个 client 端的话,那我们用 webhook ,设置手动刷新都不算太费事,但是如果端比较多的话呢,一个一个去手动刷新未免有点复杂。这样的话,我们可以借助 Spring Cloud Bus 的广播功能,让 client 端都订阅配置更新事件,当配置更新时,触发其中一个端的更新事件,Spring Cloud Bus 就把此事件广播到其他订阅端,以此来达到批量更新。

1、Spring Cloud Bus 核心原理其实就是利用消息队列做广播,所以要先有个消息队列,目前官方支持 RabbitMQ 和 kafka。

这里用的是 RabbitMQ, 所以先要搭一套 RabbitMQ 环境。请自行准备环境,这里不再赘述。我是用 docker 直接创建的,然后安装了 rabbitmq-management 插件,这样就可以在浏览器访问 15672 查看 UI 管理界面了。

2、在 client 端增加相关的包,注意,只在 client 端引入就可以。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

3、在配置文件中增加 RabbitMQ 相关配置,默认的端口应该是 5672 ,因为我是用 docker 创建的,所以有所不同。

spring:
  rabbitmq:
    host: localhost
    port: 32775
    username: guest
    password: guest

4、启动两个或多个 client 端,准备来做个测试

在启动的时候分别加上 vm option:-Dserver.port=3302 和 -Dserver.port=3303 ,然后分别启动就可以了。

5、分别打开 http://localhost:3302/autoShow 和 http://localhost:3303/autoShow,查看内容,然后修改 github 上配置文件的内容并提交。再次访问这两个地址,数据没有变化。

6、访问其中一个的 actuator/bus-refresh 地址,注意还是要用 POST 方式访问。之后查看控制台输出,会看到这两个端都有一条这样的日志输出

o.s.cloud.bus.event.RefreshListener: Received remote refresh request. Keys refreshed

7、再次访问第 5 步的两个地址,会看到内容都已经更新为修改后的数据了。

综上所述,当我们修改配置后,使用 webhook ,或者手动触发的方式 POST 请求一个 client 端的 actuator/bus-refresh 接口,就可以更新给所有端了。

结合 Eureka 使用 Spring Cloud Config

以上讲了 Spring Cloud Config 最基础的用法,但是如果我们的系统中使用了 Eureka 作为服务注册发现中心,那么 Spring Cloud Config 也应该注册到 Eureka 之上,方便其他服务消费者使用,并且可以注册多个配置中心服务端,以实现高可用。

好的,接下来就来集成 Spring Cloud Config 到 Eureka 上。

在 github 仓库中增加配置文件

启动 Eureka Server

首先启动一个 Eureka Server,之前的文章有讲过 Eureka ,可以回过头去看看。Spring Cloud Eureka 实现服务注册发现,为了清楚,这里还是把配置列出来

1、pom 中引入相关包

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

2、设置配置文件内容

bootstrap.yml

spring:
  application:
    name: kite-eureka-center
  security:
      user:
        name: test  # 用户名
        password: 123456   # 密码
  cloud:
    inetutils: ## 网卡设置
      ignoredInterfaces:  ## 忽略的网卡
        - docker0
        - veth.*
        - VM.*
      preferredNetworks:  ## 优先的网段
        - 192.168

application.yml

server:
  port: 3000
eureka:
  instance:
    hostname: eureka-center
    appname: 注册中心
  client:
    registerWithEureka: false # 单点的时候设置为 false 禁止注册自身
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://test:123456@localhost:3000/eureka
  server:
    enableSelfPreservation: false
    evictionIntervalTimerInMs: 4000

3、Application 启动类

@EnableEurekaServer
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4、启动服务,在浏览器访问 3000 端口,并输出用户名 test,密码 123456 即可进入 Eureka UI

配置 Spring Cloud Config 服务端

服务端和前面的相比也就是多了注册到 Eureka 的配置,其他地方都是一样的。

1、在 pom 中引入相关的包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- spring cloud config 服务端包 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

<!-- eureka client 端包 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2、配置文件做配置

application.yml

server:
  port: 3012
eureka:
  client:
    serviceUrl:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://test:123456@localhost:3000/eureka/
  instance:
    preferIpAddress: true
spring:
  application:
    name: config-eureka-server
  cloud:
     config:
        server:
          git:
            uri: https://github.com/huzhicheng/config-only-a-demo
            username: github 用户名
            password: github 密码
            default-label: master
            search-paths: config

相比于不加 Eureka 的版本,这里仅仅是增加了 Eureka 的配置,将配置中心注册到 Eureka ,作为服务提供者对外提供服务。

3、启动类,在 @EnableConfigServer 的基础上增加了 @EnableEurekaClient,另外也可以用 @EnableDiscoveryClient 代替 @EnableEurekaClient

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4、启动服务,之后访问 Eureka ,可以看到服务已注册成功

配置 Spring Cloud Config 客户端

客户端的配置相对来说变动大一点,加入了 Eureka 之后,就不用再直接和配置中心服务端打交道了,要通过 Eureka 来访问。另外,还是要注意客户端的 application 名称要和 github 中配置文件的名称一致。

1、pom 中引入相关的包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

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

2、配置文件

bootstrap.yml

eureka:
  client:
    serviceUrl:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://test:123456@localhost:3000/eureka/
  instance:
    preferIpAddress: true


spring:
  profiles:
    active: dev

---
spring:
  profiles: prod
  application:
    name: config-eureka-client
  cloud:
     config:
       label: master
       profile: prod
       discovery:
         enabled: true
         service-id: config-eureka-server


---
spring:
  profiles: dev
  application:
    name: config-eureka-client
  cloud:
     config:
       label: master  #指定仓库分支
       profile: dev   #指定版本 本例中建立了dev 和 prod两个版本
       discovery:
          enabled: true  # 开启
          service-id: config-eureka-server # 指定配置中心服务端的server-id 

除了注册到 Eureka 的配置外,就是配置和配置中心服务端建立关系。

其中 service-id 也就是服务端的application name。

application.yml

server:
  port: 3011
management:
  endpoint:
    shutdown:
      enabled: false
  endpoints:
    web:
      exposure:
        include: "*"

data:
  env: NaN
  user:
    username: NaN
    password: NaN

3、启动类,增加了 @EnableEurekaClient 注解,可以用 @EnableDiscoveryClient 代替

@SpringBootApplication
@EnableEurekaClient
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4、另外的配置实体类和 RESTController 和上面的一样,没有任何更改,直接参考即可。

5、启动 client 端,访问 http://localhost:3011/autoShow,即可看到配置文件内容。

这个例子只是介绍了和 Eureka 结合的最基础的情况,还可以注册到高可用的 Eureka 注册中心,另外,配置中心服务端还可以注册多个实例,同时保证注册中心的高可用。

注意事项

1. 在 git 上的配置文件的名字要和 config 的 client 端的 application name 对应;

2. 在结合 eureka 的场景中,关于 eureka 和 git config 相关的配置要放在 bootstrap.yml 中,否则会请求默认的 config server 配置,这是因为当你加了配置中心,服务就要先去配置中心获取配置,而这个时候,application.yml 配置文件还没有开始加载,而 bootstrap.yml 是最先加载的。

如果你觉得写的还可以的话,请点个「推荐」吧

欢迎关注,不定期更新本系列和其他文章
古时的风筝 ,进入公众号可以加入交流群

Guess you like

Origin www.cnblogs.com/fengzheng/p/11242128.html