07月21, 2018

Spring Cloud [02_配置中心_Spring_Config]

微服务架构因为其分布式结构,各自服务间分散的配置加大了运维成本。spring config配置中心将所有配置集中管理,配合注册中心等中间件实现配置的灵活订阅、负载高可用与动态刷新等功能,极大的简化了配置管理的难度。

Config Server

配置中心服务端:

  • 集中管理所有配置文件
  • 为客户端提供统一的配置文件获取入口
  • 动态触发配置刷新
添加依赖pom.xml
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
</dependency> 
启动类开启配置中心
@SpringBootApplication
// Eureka注册服务发现
@EnableDiscoveryClient
// 开启配置服务中心
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
配置远程库连接方式

application.yml

spring:
  application:
    name: config_server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/check321/config-repo.git
          username: name4git
          password: pwd4git
# 向Eureka注册配置中心          
eureka:
  client:
    service-url:
      defaultZone: http://node01:8701/eureka/
server:
  port: 8686
配置中心远程仓库

将配置文件上传至git远程仓库.

获取配置
  • 启动服务后在Eureka服务中心发现配置中心 alt

  • 访问{fileName}-{lable}.yml获取托管的配置

 BAR-SERVICE:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

Config Client

配置客户端即各服务配置的托管者,本地省去了复杂的配置文件管理,仅需要注册Eureka并订阅ConfigServer的服务。

配置客户端依赖

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>
订阅配置中心

因为application.yml文件被托管至配置中心,所以客户端本地仅须配置bootstrap.yml订阅服务,它将优先于前者配置生效。

bootstrap.yml

spring:
  application:
    name: foo-service
  # 订阅配置中心  
  cloud:
    config:
      discovery:
        enabled: true
        service-id: CONFIG_SERVER
  # 注册服务      
  eureka:
  client:
    service-url:
      defaultZone: http://node01:8701/eureka/      
获取配置
  • 创建测试接口,返回配置文件中的键值
 @GetMapping("/v")
    public String version() {
       return systemConfig.toString();
    }
@Data
@Configuration
@ConfigurationProperties("system")
public class SystemConfig {

    private String branch;

    private String version;
}

applocation.yml新增system.version

system:
    branch: dev
    version: 1.1.4

Spring Bus 动态刷新

在现实场景中,在配置集中化后我们希望对于频繁更新配置的服务可以实现动态感知并自动获取,借助Spring Bus消息总线可以完成这一需求。

消息中间件

当消息总线感知到远程配置库的配置更新后需要通过消息中间件异步协同配置中心与客户端之间的配置更新,为此这里选用RabbitMQ做为中间件承载这一任务。

配置总线
  • Config Server
    <!-- RabbitMQ -->
  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
    <!-- SpringBus -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

新增MQ配置

 rabbitmq:
    host: xxx.xxx.xxx
    port: 5672
    username: xxx
    password: xxx
  • Config Client

Spring Bus MQ依赖

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

MQ配置同Config Server

在需要动态刷新的类新增@RefreshScope

@Data
@Configuration
@ConfigurationProperties("system")
@RefreshScope
public class SystemConfig {

    private String branch;

    private String version;
}
  • MQ控制台 重新启动服务后,ConfigServer 与 Client随机创建了两个消息队列,Spring Bus将会通过该队列完成配置操作的消息传递。 alt

  • Actuator Spring Bus在Config Server暴露了[/actuator/bus-refresh]接口,调用该接口就会触发消息刷新的机制。

    Mapped "{[/actuator/bus-refresh],methods=[POST]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)

  • 将配置远程仓库的system.config更改成1.1.5 alt

  • 调用ConfigServer的/actuator/bus-refresh 队列有配置更新通讯信息 alt

  • 再次访问http://localhost:9001/v alt

刷新成功~

WebHooks实现Push Event监控

几乎每一个Git远程仓库都支持WebHooks的配置,通过监听特定的仓库事件实现Hooks钩子方法的回调。 正好在每一次更新远程配置仓库的配置后利用Hooks回调ConfigServer的bus-refresh方法,再通过消息总线下发配置刷新的操作。

  • GitHub WebHooks配置 alt

  • Issue 在Spring Cloud最新的 Finchley.RELEASE版本中对于JSON格式的WebHooks会抛出转换错误,等待后续的官方修复。 Issue报告


本文链接:https://check321.net/post/springcloud_config.html

-- EOF --