五、SpringCloud配置中心

CY 2019年03月19日 10次浏览

随着工程量的越来越大,每个工程里面都需要去进行配置,导致大量的时间都花费在了修改配置文件上,所以集中配置非常的重要。

需要有一个配置中心,然后其他服务全部从配置中心上获取配置,获取到配置后可以动态的在当前服务中更新配置信息。

Spring Cloud Config

服务端的搭建

坐标:

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

配置:

spring:
  application:
    name: cloud-config-server
  cloud:
    config:
      server:
        git:
          uri: git@gitee.com:lunaticy/config.git
      label: master

上面配置文件配置了git的远程地址,还规定了到master分支上面去找文件

这里有个坑,如果是Windows电脑,不要使用Git Bash去生成SSH密钥,使用默认的CMD就好了,不然总是鉴权失败,原因是私钥不是RSA,而是OpenSSH,这就导致私钥不正确。

启动类:

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

启动后有5种访问方式:

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

他们分别对应的URL是:

http://localhost:8844/cloud/dev/master (JSON)
http://localhost:8844/cloud-dev.yml (Yaml)
http://localhost:8844/master/cloud-dev.yml (Yaml)
http://localhost:8844/cloud-dev.properties (Properties)
http://localhost:8844/master/cloud-dev.properties (Properties)

客户端的搭建

依赖:

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

配置(bootstrap.yaml):

bootstrap.yamlapplication.yaml优先级高一些,所以适用于动态配置文件的加载。

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

一个普普通通的启动类,还有一个普普通通的Controller

@SpringBootApplication
public class ConfigClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }
}
@RestController
public class ConfigController {

    @Value("${display.info}")
    private String info;

    @RequestMapping("info")
    public String info() {
        return info;
    }
}

启动后,访问接口,可以看到Git上配置文件种存储的字符串就代表成功了。

上面演示了只有一个客户端的情况,Git上面的配置文件更改了之后,发现Config Server接口中的配置变了,但是Config Client里面的配置并没有改变,重启后就改变了。

如果有超级多个客户端,不可能一直去做微服务的重启操作,所以就需要有一个热配置,也就是动态刷新配置。

动态刷新配置

该操作在客户端

首先需要加入依赖:

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

然后暴露出端点,在之前Hystrix Dashboard配置的基础上添加一个refresh

management:
  endpoints:
    web:
      exposure:
        include: health, info, hystrix.stream, refresh

接下来是最重要的一步,在之前的Controller上面加上@RefreshScope,主意一定是作用域的Controller上,不能加载主启动类上。

@RestController
@RefreshScope
public class ConfigController {
	...
}

每次修改之后用post方法发送refresh请求就可以做到动态的加载配置文件了。

http://localhost:8855/actuator/refresh

虽然达成目标,但是这还是在一个微服务的基础上,如果微服务数量相当多,难道要每个微服务发送一个请求?这也好实现,但是还要精确的控制哪些微服务需要刷新,哪些微服务不需要刷新。SpringCloud也有一套解决方案,叫做Spring Cloud Bus,消息总线。

Spring Cloud Bus

实现原理就是用消息中间件做所有微服务的通知工作,只需要发送一次请求,就会通知给其他微服务,其他微服务收到通知后就会自动的刷新配置。

发送一次请求,发给谁合适呢,有两种方案:

  • 发给Config Server

    这种方案是最好的方案,让配置中心去通知所有使用了配置中心的微服务

  • 发送Config Client

    这种方案并不优雅,因为会让其中的一个微服务多做一点事情,而且成千上万个微服务之中就它特殊,也不是一件漂亮的事情。

安装RabbitMQ

略掉了... 在之前RabbitMQ的文章中记录过...

而且网上的教程也不少...

Bus全局动态刷新

该操作在服务端

因为要使用Config Server做广播的一端,所以就需要Config Server来暴露一个接口,访问该接口就可以广播给所有的Config Client

引入依赖:

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

添加配置:

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

management:
  endpoints:
    web:
      exposure:
        include: bus-refresh

可以看到配置文件配置了RabbitMQ的连接,还暴漏了端点bus-refresh

服务端就改写完成了,接下来需要新建几个客户端,以一个为例:

加入一样的依赖:

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

配置文件配置一下RabbitMQ就可以了。

启动服务端和几个客户端进行测试,客户端如果不想要新建好几个,可以用新建启动配置的方式:

新建启动配置

然后用Postman来发送一个Post请求

http://localhost:8844/actuator/bus-refresh

可以看到批量的进行配置刷新了。

Bus定点动态刷新

和上面唯一的不同是Postman发送的接口不一样了。

http://localhost:8844/actuator/bus-refresh/config-client:8855

在原来的URL上面添加了服务名:端口号

除了使用Postman以外,可以使用远程仓库的Webhook功能来进行实时的配置改变,也就相当于改了文件之后Gitee会自动触发某个接口,当然这个接口需要在公网才可以。