SpringBoot项目中的配置文件如何动态刷新

SpringBoot 项目一般将一些重要的参数配置在application.yml或者application.properites中,譬如外部服务链接、数据库地址及帐号信息、某些业务变量。随着业务的开展,实现一个完整的业务流程一般须要开发并管理多个微服务,一旦这些参数调整,须要修改多个微服务的配置并重启,这将给运维及生产带来额外的工做和影响。为了解决这个问题,咱们能够将这些配置抽取到一个公共的地方,可参照另外一篇文章“Spring Cloud 微服务公共配置处理请添加连接描述”,将微服务的公共配置抽取出来。完成抽取只是第一步,一旦数据库的帐号或者外部服务链接修改,服务仍是须要逐个重启,如何解决这个问题呢?git

Spring Cloud的message和integration机制,容许咱们经过cloud bus,将变动通知到每个服务,实现动态刷新,其架构设计以下(摘自网络)web

SpringBoot项目中的配置文件如何动态刷新

实现这个过程,须要引入spring cloud的相关组件:注册服务、消息服务、集成服务、配置服务等,以及一个可用的消息队列。下面我将以Springboot2.1.8,cloud版本Greenwich.SR3为例,介绍如何实现。spring

服务清单数据库

  • EurekaServer - 注册服务,实际项目可选其余,此处仅做示例。
  • ConfigServer - 配置服务
  • ConfigClient1 - 微服务应用1,经过config server获取配置
  • ConfigClient2 - 微服务应用2,经过config server获取配置
  • RabbitMQ - 消息服务,用来接收和转发 bus消息
  • Git服务 - 配置文件的存储和修改,实际项目中可选其余替代方案,此处仅做示例。

1. EurekaServer

Eureka服务比较简单,配置和启动效果以下。bootstrap

server:
  port: 7777
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      default-zone: http://${eureka.instance.hostname}:${server.port}/eureka/

SpringBoot项目中的配置文件如何动态刷新

2. ConfigServer

Configserver须要引入bus-amqp,pom配置以下:浏览器

  1. boot相关springboot

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</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-amqp</artifactId>
        </dependency>
  2. cloud相关
    <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-bus</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-monitor</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream</artifactId>
        </dependency>

application的配置以下,网络

  1. spring config相关:
    SpringBoot项目中的配置文件如何动态刷新架构

  2. management相关:
    SpringBoot项目中的配置文件如何动态刷新

3. ConfigClient01 和ConfigClient02

  1. bootstrap.yml配置
    SpringBoot项目中的配置文件如何动态刷新

management的配置是为了支持bus-fresh,rabbitmq须要同时配置在bootstrap和application中。app

  1. application配置
    SpringBoot项目中的配置文件如何动态刷新

主要包括eureka配置,rabbitmq配置及用来测试ext.key。configclient02的配置和01几乎一致,仅端口和应用名称不一样。

因此服务启动后,能够看到eureka的管理界面以下:
SpringBoot项目中的配置文件如何动态刷新

4. git仓库中配置服务application文件的替代版

SpringBoot项目中的配置文件如何动态刷新
内容分别以下:

ext.key=hello client 111

ext.key=hello client 222

这个时候就能够测试了。测试方式能够经过浏览器访问configserver,直接请求配置文件,也能够经过程序测试,先说经过浏览器访问。

springboot项目启动时,若是引入了config-client和context包,则会自动根据bootstrap指定的地址获取配置,请求方式以下:
http://${spring.cloud.config.uri}/${spring.cloud.config.name}/<spring.cloud.config.profile>/<lspring.cloud.config.label>;, 参照bootstrap.yml的定义。

这个项目直接请求:http://localhost:8021/cfg_client01/dev/aliyun_dev, 返回以下:
SpringBoot项目中的配置文件如何动态刷新
这种请求方式,也是springboot项目启动时初始化的请求方式。

下面以更实际的方式测试,在controller中引用一个变量,ext.key, 查看属性的变化。

@RestController
@RequestMapping("/test")
@RefreshScope
public class IndexController {

    @Value("${ext.key}")
    private String key;

    @GetMapping("/key")
    public String printKey() {
        return key;
    }
}

controller很简单,惟一须要注意的是,必定要加上@RefreshScope,由于spring在刷新时,会基于这个注解,肯定要不要刷新bean或者方法内的引用属性。
第一次直接请求:
SpringBoot项目中的配置文件如何动态刷新

SpringBoot项目中的配置文件如何动态刷新

如今修改git上的配置文件,将ext.key改为111000和222000。
SpringBoot项目中的配置文件如何动态刷新

SpringBoot项目中的配置文件如何动态刷新

这个时候就能够调用spring的bus-refresh了。调用refresh的时候,能够直接调用server的,也能够调用某个具体的client,我但愿一次刷新,全部的变动都生效,因此直接调用configserver的bus-refresh。固然,也有人将git的commit配置成hookurl,但这种方式在生产环境会有些风险,咱们的作法是,配置文件修改并确认提交后,手动执行一次bus-refrehs。

SpringBoot项目中的配置文件如何动态刷新

刷新完成后,分别在请求extkey,查看返回:
SpringBoot项目中的配置文件如何动态刷新

SpringBoot项目中的配置文件如何动态刷新

能够看到两个应用服务的属性都已经刷新。实现刷新的关键有如下几个:

  • 消息队列的在bootstrap和applicaiton中同时配置
  • management.endpoints.web.exposure.include属性须要配成"*"或者 bus-refresh,由于这个地址默认不支持,直接调用会出现404.
  • 验证服务,网上不少介绍都须要关闭,我测试过程当中,没有关闭,可是能够直接访问。实践者能够根据本身的服务配置调整。

基于此,咱们就实践了配置文件中属性的动态刷新,实现一次刷新,全部服务生效。这种@Value引用的属性能够这么刷新,那么数据库链接参数呢?下一篇文章,我将介绍如何经过刷新机制,实如今不重启服务的前提下,动态修改数据库的链接参数或者密码。

相关文章
相关标签/搜索