分佈式環境下的統一配置框架,已經有很多了,好比百度的disconf,阿里的diamandhtml
Spring Cloud Config爲分佈式系統中的外部配置提供服務器和客戶端支持,使用Config Server,您能夠在全部環境中管理應用程序的外部屬性。客戶端和服務器上的概念映射與Spring Environment和PropertySource抽象相同,mysql
所以它們與Spring應用程序很是契合,但能夠與任何以任何語言運行的應用程序一塊兒使用。隨着應用程序經過從開發人員到測試和生產的部署流程,您能夠管理這些環境之間的配置,並肯定應用程序具備遷移時須要運行的一切。git
服務器存儲後端的默認實現使用git,所以它輕鬆支持標籤版本的配置環境,以及能夠訪問用於管理內容的各類工具。很容易添加替代實現,並使用Spring配置將其插入。web
一個應用中不僅是代碼,還須要鏈接資源和其它應用,常常有不少須要外部設置的項去調整應用行爲,如切換不一樣的數據庫,設置功能開關等。spring
隨着系統微服務的不斷增長,首要考慮的是系統的可伸縮、可擴展性好,隨之就是一個配置管理的問題。各自管各自的開發時沒什麼問題,到了線上以後管理就會很頭疼,到了要大規模更新就更煩了。sql
並且你不可能中止你的服務集羣去更新的你配置,這是不現實的作法,所以springcloud配置中心就是一個比較好的解決方案,下圖就是一個springcloud配置中心的解決方案:數據庫
常見的配置中心的實現方法有:json
1.硬編碼(缺點:須要修改代碼,風險大)
bootstrap
2.放在xml等配置文件中,和應用一塊兒打包(缺點:須要從新打包和重啓)
後端
3.文件系統中(缺點:依賴操做系統等)
4.環境變量(缺點:有大量的配置須要人工設置到環境變量中,不便於管理,且依賴平臺) 5.雲端存儲(缺點:與其餘應用耦合)
Spring Cloud Config就是雲端存儲配置信息的,它具備中心化,版本控制,支持動態更新,平臺獨立,語言獨立等特性。其特色是:
1.提供服務端和客戶端支持(spring cloud config server和spring cloud config client) 2.集中式管理分佈式環境下的應用配置 3.基於Spring環境,無縫與Spring應用集成 4.可用於任何語言開發的程序 5.默認實現基於git倉庫,能夠進行版本管理 6.可替換自定義實現
spring cloud config包括兩部分:
1.spring cloud config server 做爲配置中心的服務端:
1.拉取配置時更新git倉庫副本,保證是最新結果
2.支持數據結構豐富,yml, json, properties 等
3.配合 eureke 可實現服務發現,配合 cloud bus 可實現配置推送更新
4.配置存儲基於 git 倉庫,可進行版本管理
5.簡單可靠,有豐富的配套方案
2.Spring Cloud Config Client 客戶端:
1.Spring Boot項目不須要改動任何代碼,加入一個啓動配置文件指明使用ConfigServer上哪一個配置文件便可
SpringCloud Config與百度的disconf之類的有很大不一樣,主要區別在於下面三點:
1.配置的存儲方式不一樣:disconf是把配置信息保存在mysql、zookeeper中,而spring cloud config是將配置保存在git/svn上 (即:配置當成源代碼同樣管理)
2.配置的管理方式不一樣:spring cloud config沒有相似disconf的統一管理界面,既然把配置都當成git之類的源碼來看待了,git的管理界面,就是配置的管理界面
3.配置變化的通知機制不一樣:disconf中配置變化後,依賴zk的事件watcher來通知應用,而spring cloud config則是依賴git每次push後,觸發webhook回調,最終觸發spring cloud bus(消息總線),而後由消息總線通知相關的應用。
從配置變化的通知機制上看,若是有100個應用節點,都依賴於統一配置,若是修改了配置,只想讓某幾個節點"灰度"更新配置,spring cloud config server更容易作到,這一點相對disconf更靈活
首先SpringCloud Config 是分爲Server端和Client端的,Server端負責管理配置,Client端用來加載配置。咱們每個爲服務都要集成一個Client端的。上面也提到過。所以,咱們如今看一下Config的Server端的Demo實現。
首先在原來的項目中新建一個springcloud-config-server模塊,而且引入相關依賴,以下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> <version>1.4.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.5.RELEASE</version> </dependency>
咱們能夠看到引入了Eureka,爲何呢?很明顯是爲了高可用。
接着在啓動類上面加入@EnableConfigServer註解,表示這裏是配置中心服務。還有Eureka的客戶端的註解代碼以下:
@SpringBootApplication @EnableConfigServer @EnableDiscoveryClient public class ConfigApplication { public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); } }
application.yml配置以下:
server: port: 7000 #服務名字 spring: application: name: config-server cloud: config: server: git: #git 倉庫的地址 uri: https://gitee.com/xxxx/springcloud-config.git #git 倉庫的帳號密碼 username: xxx password: xxx #加入註冊中心,實現高可用 eureka: client: service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
注意了,前提是你必需要在git倉庫中先創建一個倉庫,而後配置兩個配置,一個開發dev,一個測試test 以下圖:
dev的內容以下:
test的內容以下:
好了,讓咱們把springcloud-config模塊啓動起來,啓動啓動類,運行,訪問git倉庫中的cloud-config-dev.properties,以下:
接下來,咱們進行springcloud Config的Client端的Demo,以下:
首先引入Client端的相關依賴,以下:
<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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> <version>1.4.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.5.RELEASE</version> </dependency>
這裏提一下,爲何須要引入前面的actuctor依賴,由於,咱們Client端須要在不重啓的狀況下,及時更新拉取加載配置中心的改變,而後修改內存中的配置的值。
接着在Client啓動類的打上@EnableDiscoveryClient的註解,來註冊到註冊中心去,以下:
@SpringBootApplication @EnableDiscoveryClient public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } }
接下來這步驟很關鍵,就是要將Client模塊下的application.yml文件改成bootstrap.yml,這是很關鍵的,由於bootstrap.yml是比application.yml先加載的。bootstrap.yml優先級高於application.yml。就比如如,你應用程序都跑起來了,你配置還沒加載,這不是扯淡嗎?
以下:
server: port: 7005 spring: application: name: cloud-config cloud: config: #啓動什麼環境下的配置,dev 表示開發環境,這跟你倉庫的文件的後綴有關,好比,倉庫配置文件命名格式是cloud-config-dev.properties,因此profile 就要寫dev profile: dev
#面向服務,容許被發現 discovery: enabled: true #這個名字是Config Server端的服務名字,不能瞎寫。 service-id: config-server #註冊中心 eureka: client: service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/ #是否須要權限拉去,默認是true,若是不false就不容許你去拉取配置中心Server更新的內容 management: security: enabled: false
接着寫一段測試代碼,以下,創建一個測試Controller,代碼以下:
@RestController //這裏面的屬性有可能會更新的,git中的配置中心變化的話就要刷新,沒有這個註解內,配置就不能及時更新 @RefreshScope public class TestController { @Value("${name}") private String name; @Value("${age}") private Integer age; @RequestMapping("/test") public String test(){ return this.name+this.age; } }
接着啓動啓動該工程,運行結果以下:
首先咱們咱們先看沒更新配置以前的值,以下:
接着咱們去git倉庫中修改age的值爲24,再用postman來發送post請求localhost:7005/refresh,以下:
能夠看到postman返回config.client.version信息,表示告知Client,遠程的倉庫中的配置中心已經更新了的配置版本信息,改變的值爲age。
接着咱們繼續刷新瀏覽器,localhost:7005/test,看一下年齡是否更新了,以下:
能夠看到年齡跟新到24了。
可是這樣就行了嗎?雖然服務沒有重啓,可是咱們要一個服務一個服務的發送post請求,咱們能受的了嗎?這比以前的沒配置中心好多了,那麼咱們如何繼續避免挨個挨個的向服務發送Post請求來告知服務,你的配置信息改變了,須要及時修改內存中的配置信息。
這時候咱們就不要忘記消息隊列的發佈訂閱模型。讓全部爲服務來訂閱這個事件,當這個事件發生改變了,就能夠通知全部微服務去更新它們的內存中的配置信息。這時Bus消息總線就能解決,這留到下一篇隨筆講解。