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引用的屬性能夠這麼刷新,那麼數據庫鏈接參數呢?下一篇文章,我將介紹如何經過刷新機制,實如今不重啓服務的前提下,動態修改數據庫的鏈接參數或者密碼。

相關文章
相關標籤/搜索