SpringBoot 項目一般將一些重要的參數配置在application.yml或者application.properites中,譬如外部服務鏈接、數據庫地址及帳號信息、某些業務變量。隨着業務的開展,實現一個完整的業務流程一般須要開發並管理多個微服務,一旦這些參數調整,須要修改多個微服務的配置並重啓,這將給運維及生產帶來額外的工做和影響。爲了解決這個問題,咱們能夠將這些配置抽取到一個公共的地方,可參照另外一篇文章「Spring Cloud 微服務公共配置處理請添加連接描述」,將微服務的公共配置抽取出來。完成抽取只是第一步,一旦數據庫的帳號或者外部服務鏈接修改,服務仍是須要逐個重啓,如何解決這個問題呢?git
Spring Cloud的message和integration機制,容許咱們經過cloud bus,將變動通知到每個服務,實現動態刷新,其架構設計以下(摘自網絡)web
實現這個過程,須要引入spring cloud的相關組件:註冊服務、消息服務、集成服務、配置服務等,以及一個可用的消息隊列。下面我將以Springboot2.1.8,cloud版本Greenwich.SR3爲例,介紹如何實現。spring
服務清單數據庫
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/
Configserver須要引入bus-amqp,pom配置以下:瀏覽器
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>
<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的配置以下,網絡
spring config相關:
架構
management的配置是爲了支持bus-fresh,rabbitmq須要同時配置在bootstrap和application中。app
主要包括eureka配置,rabbitmq配置及用來測試ext.key。configclient02的配置和01幾乎一致,僅端口和應用名稱不一樣。
因此服務啓動後,能夠看到eureka的管理界面以下:
內容分別以下:
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項目啓動時初始化的請求方式。
下面以更實際的方式測試,在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或者方法內的引用屬性。
第一次直接請求:
如今修改git上的配置文件,將ext.key改爲111000和222000。
這個時候就能夠調用spring的bus-refresh了。調用refresh的時候,能夠直接調用server的,也能夠調用某個具體的client,我但願一次刷新,全部的變動都生效,因此直接調用configserver的bus-refresh。固然,也有人將git的commit配置成hookurl,但這種方式在生產環境會有些風險,咱們的作法是,配置文件修改並確認提交後,手動執行一次bus-refrehs。
刷新完成後,分別在請求extkey,查看返回:
能夠看到兩個應用服務的屬性都已經刷新。實現刷新的關鍵有如下幾個:
基於此,咱們就實踐了配置文件中屬性的動態刷新,實現一次刷新,全部服務生效。這種@Value引用的屬性能夠這麼刷新,那麼數據庫鏈接參數呢?下一篇文章,我將介紹如何經過刷新機制,實如今不重啓服務的前提下,動態修改數據庫的鏈接參數或者密碼。