Springcloud使用Bus配合Config实现配置更新

2020-06-23  本文已影响0人  Martain

配置中心的痛点

​ 我们知道SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置,但是它无法很方便的实现多客户端的配置一键刷新,现在使用springcloud Bus 配合 springcloud Config 可以实现配置的动态刷新,达到一次通知,处处生效的效果。

什么是总线

在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播-些需要让其他连接在该主题上的实例都知道的消息。

关于springcloud Bus

Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。Spring Clud Bus目前支持RabbitMQKafka。SpringCloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务的通信通道。Bus支持如下两种广播方式:

Bus直接通知给其中⼀个客户端,由这个客户端开始蔓延,传播给其他所有客户端

通知客户端再蔓延

通知给配置中⼼的服务端,由服务端⼴播给所有客户端

服务端再广播

相比这两种方式,方式二我觉得会更加合适,因为方式一打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责。破坏了微服务各节点的对等性。因为第一种,有一个客户端需要额外的承担刷新职责,而其他的客户端却只有业务职责有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改。

使用SpringCloud Bus

SpringCloud Bus目前支持的消息代理有RabbitMQKafka,在这里我选择的是使用RabbitMQ并且选择方式二来进行配置更新通知

基本环境

服务端配置

添加依赖

 <!--config server-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- 添加消息总线RabbitMQ支持 -->
<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>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka client-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

修改application.yml

server:
  port: 7070
spring:
  application:
    name: cloud-config-server
  # config 配置
  cloud:
    config:
      server:
        git:
          uri: https://github.com/martaintao/spring-config-center-demo.git # 因为我这个是public的仓库,所以不需要认证。
      label: master
  # rabbitmq 配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

# eureka注册中心配置
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册消息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8080/eureka/

# 配置暴端点
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh' # 暴露端点

启动类

使用@EnableConfigServer注解来开启配置服务

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

客户端配置

添加依赖

 <!-- 添加消息总线RabbitMQ支持 -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<!--   spring config     -->
<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>
<!--监控-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--eureka client-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

修改 bootstrap.yml

注意,这里是创建bootstrap.yml,这个配置⽂件的作⽤是,先到配置中⼼加载配置,然后加载到application.yml中。

application.yml是用户级的资源配置项。

bootstrap.yml是系统级的,优先级比application.yml更高。

server:
  port: 7001 
spring:
  application:
    name: cloud-eureka-consumer-useradmin
  cloud:
    config:
      label: master # 分支名称
      name: config  # 配置文件名称 列如config-dev.yml 名称就是config
      profile: dev  # 环境(读取后缀)
      uri: http://127.0.0.1:7070 # 配置中心地址
  # rabbitMQ 配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
# 注册中心配置
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册消息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8080/eureka/ 
# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

测试接口

直接访问 /getConfigInfo来获取远程配置文件中的config.info信息

@RestController
@RefreshScope
public class ConfigClientController {

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

    @GetMapping("/getConfigInfo")
    public String getConfigInfo(){
        return configInfo;
    }
}

启动类

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

测试

先启动注册中心和RabbitMQ,然后再启动配置服务端以及客户端。

定点通知

刚刚我们演示了方式二,发送指令给配置中心服务,然后所有的客户端都全部更新,但是有的时候我们可能只希望更改其中的一部分客户端而已,是否可以指定呢?答案是肯定的。

我们知道了发送POST请求/actuator/bus-refresh给服务端会让所有的客户端都应用最新配置。我们可以在后面指定某个客户端。比如:

POST http://localhost:7070/actuator/bus-refresh/cloud-eureka-consumer-useradmin:7001

如上就会通知微服务名为cloud-eureka-consumer-useradmin且端口号为7001的服务进行更新。由此我们也知道了指定方式是 微服务名称+端口号

上一篇下一篇

猜你喜欢

热点阅读