若是微服務架構中沒有使用統一配置中心時,所存在的問題:java
在SpringCloud中咱們使用config組件來做爲統一配置中心:git
廢話很少說,本小節咱們來開發統一配置中心的server端,在IDEA中新建一個Spring Initializr項目,並選擇相應的模塊:web
項目的pom.xml文件配置的依賴以下:spring
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-monitor</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> </dependencies>
由於config server是須要到git上拉取配置文件的,因此還須要在遠程的git上新建一個存放配置文件的倉庫,我這裏使用的是碼雲:docker
建立好後,新建一個文件,而後把訂單服務的配置文件內容粘貼進來:json
注:我這裏事先已經存在一個商品服務和訂單服務bootstrap
回到config項目中,編輯application.yml配置文件內容以下:瀏覽器
spring: application: name: config cloud: config: server: git: uri: https://gitee.com/Zero-One/config-repo # 遠程git倉庫的地址 username: username # 以及相應的帳戶名 password: password # 和密碼 basedir: E:\Java_IDEA\config\basedir # 可使用這個配置項來指定本地git倉庫的路徑 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ server: port: 8974
在啓動類上,加上@EnableConfigServer
註解,聲明這是一個config-server。代碼以下:安全
package org.zero.springcloud.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient @EnableConfigServer public class ConfigApplication { public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); } }
啓動項目,訪問以下地址,能夠看到可以訪問到配置文件的內容:bash
若是訪問.properties格式的,還會自動進行轉換:
.json格式的也可以進行轉換:
注:若是配置文件的內容格式有問題的話,訪問會報500錯誤。咱們能夠利用這個特性,來檢查咱們的配置文件是否正確
在上圖訪問的地址中能夠發現,訪問的配置文件名後面還有一個-a,這實際上是config的訪問規則。後面必需要跟個-xxx,因此在建立文件的時候,最好是按這種命名規則來建立。配置文件的訪問規則以下:
/{name}-{profiles}.yml /{label}/{name}-{profiles}.yml name : 文件名,通常以服務名來命名 profiles : 通常做爲環境標識 lable : 分支(branch),指定訪問某分支下的配置文件
有一點值得注意的是,若是有兩個前綴名相同文件,例如一個order.yml,一個order-dev.yml。那麼在訪問相同前綴的文件時,config-server會對這兩個文件進行一個合併。例如order.yml有一段配置是order-dev.yml沒有的,理應訪問order-dev.yml的時候是沒有那段配置的,但訪問的結果倒是它倆合併以後的內容,即order-dev.yml會擁有order.yml裏所配置的內容。
除此以外還有一點就是,隨着後期微服務數量的增長,配置文件的數量天然也會隨着增長,並且實際的企業項目中都會在不一樣的部署環境使用不一樣的配置文件,例如開發環境(dev)、測試環境(test)、生產環境(product)等。因此一個服務至少會有三個以上的配置文件,若是咱們將這些配置文件直接放在git倉庫的根目錄下的話,就會顯得很雜亂,不便於查看、修改。以下示例:
這時咱們很天然的會想到將不一樣服務的配置文件放到以服務名命名的目錄下,例如:
這樣感受就好多了,想找哪一個服務的配置文件直接去相應的目錄下找就能夠了。可是當你開開心心的將配置文件整理到一個個的目錄裏並重啓了config server後,就會發現這些配置文件全都加載不到了。這是由於config server默認狀況下只會搜索git倉庫根路徑下的配置文件,因此咱們還須要加上一個配置項:search-paths,該配置項用於指定config server搜索哪些路徑下的配置文件,須要注意的是這個路徑是相對於git倉庫的,並不是是項目的路徑。以下示例:
spring: application: name: config cloud: config: server: git: ... search-paths: /** # 指定搜索根路徑下的全部目錄,如有多個路徑使用逗號隔開
在上一小節中,咱們介紹了config-server的使用以及配置文件的訪問規則,本小節將介紹config-client端的使用,咱們以訂單服務爲例。
在訂單服務工程的pom.xml文件中,增長以下依賴配置:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency>
注:商品服務工程中也增長這個依賴,這樣兩個服務均可以從config-server中讀取配置了
而後將application.yml重命名爲bootstrap.yml,並修改內容以下:
spring: application: name: order cloud: config: discovery: enabled: true service-id: CONFIG # 註冊中心的服務名 profile: dev # 指定配置文件的環境
注:之因此要用bootstrap.yml,是由於啓動SpringBoot項目時,會優先讀取bootstrap.yml裏的配置,而後纔會讀取application.yml。若是不經過bootstrap.yml裏的配置,先從配置中心拉下相應的配置文件,就會報錯
重啓項目,使用建立訂單接口,測試一下是否正常:
統一配置中心和服務註冊中心同樣,都是須要高可用的,否則配置文件都沒有的話,項目天然無法跑起來了。因此咱們來看看如何使config-server可以高可用。
config-server也屬因而一個微服務,因此讓其高可用很簡單,只須要啓動多個服務實例便可。首先咱們來複制幾個config-server的實例,跑在不一樣的端口上:
啓動後,到eureka上能夠看到也都註冊成功了,這樣咱們就有了三個config-server實例:
其餘服務經過負載均衡策略,就可以調用這幾個config-server實例,輕鬆實現高可用
還有一個須要注意的點是服務註冊中心地址端口的問題,咱們都知道eureka-server的默認端口是8761,若是咱們如今將eureka-server的端口改爲8762,那麼訂單服務就會啓動不了。由於在bootstrap.yml配置文件中,並無配置eureka-server的地址。
項目啓動的時候會優先讀取bootstrap.yml,按照配置的內容去配置中心拉取配置文件,可是在此以前訂單服務須要先去註冊中心上找配置中心的調用地址,若是eureka-server端口更改了的話,就會訪問不到配置中心,天然也就沒法調用配置中心拉取配置文件了,如今咱們之因此能夠訪問是由於SpringBoot默認訪問的是本地的8761端口。
因此咱們須要修改遠程git倉庫上的配置文件內容以下:
而後在bootstrap.yml中增長eureka-server的配置纔對:
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
這也是一個小細節,若是沒有注意的話,容易掉進這個坑。
在上兩個小節中,咱們學習了統一配置中心的server端以及client端的使用,也成功拉取了相應的配置文件。可是這樣仍然不夠,由於還不能作到自動刷新配置文件,例如我在git上更改了配置文件,還須要重啓服務纔可以讀取到最新的配置。因此本小節將介紹一下如何使用Spring Cloud Bus實現自動刷新配置,Bus在這裏是總線的意思。
示意圖:
Spring Cloud Bus會向外提供一個http接口,即圖中的/actuator/bus-refresh。咱們將這個接口配置到遠程的git上,當git上的文件內容發生變更時,就會自動調用/bus-refresh接口。Bus就會通知config-server,config-server會發布更新消息到消息隊列中,其餘服務訂閱到該消息就會信息刷新,從而實現整個微服務進行自動刷新。
因爲實現配置自動刷新,須要用到消息中間件,因此還得安裝,我這裏使用RabbitMQ。而且是在CentOS上使用docker進行安裝,docker的版本以下:
[root@01server ~]# docker info |grep "Server Version" Server Version: 18.03.1-ce [root@01server ~]#
安裝並啓動rabbitmq:
[root@01server ~]# docker run -d --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.7.3-management ... [root@01server ~]#
進入容器裏,添加超級管理員用戶:
[root@01server ~]# docker exec -it 1ca60f11d6d9 bash # 進入容器 root@my-rabbit:/# rabbitmqctl add_user admin password # 添加用戶,用戶名爲admin,密碼爲password Adding user "admin" ... root@my-rabbit:/# rabbitmqctl set_user_tags admin administrator # 設置用戶權限爲超級管理員 Setting tags for user "admin" to [administrator] ... root@my-rabbit:/# rabbitmqctl set_permissions -p /${user_name} admin '.*' '.*' '.*' # 設置遠程登陸權限 root@my-rabbit:/#
若是你的系統防火牆沒有關閉的話,還須要開放相應的端口:
[root@01server ~]# firewall-cmd --zone=public --add-port=15672/tcp --permanent success [root@01server ~]# firewall-cmd --zone=public --add-port=5672/tcp --permanent success [root@01server ~]# firewall-cmd --reload success [root@01server ~]#
使用瀏覽器訪問${ip}:15672
,進入登陸界面:
登陸以後才能進入到管理頁面:
安裝好RabbitMQ後,咱們就能夠着手實現配置的刷新了。首先咱們須要在config項目中,增長Spring Cloud Bus依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
注:商品服務以及訂單服務也須要加入這個依賴
而後在配置文件中,配置rabbitmq的地址以及用戶密碼,修改config服務的配置以下:
spring: application: name: config cloud: config: server: git: uri: https://gitee.com/Zero-One/config-repo username: username password: password basedir: E:\Java_IDEA\config\basedir # 配置rabbitmq的地址以及用戶密碼 rabbitmq: host: 192.168.190.129 port: 5672 username: admin password: admin eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ # 容許/actuator/bus-refresh接口被外部調用 management: endpoints: web: exposure: include: "*"
修改商品服務的配置以下:
spring: application: name: product cloud: config: discovery: enabled: true service-id: CONFIG profile: dev rabbitmq: host: 192.168.190.129 port: 5672 username: admin password: admin eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
修改訂單服務的配置以下:
spring: application: name: order cloud: config: discovery: enabled: true service-id: CONFIG profile: dev rabbitmq: host: 192.168.190.129 port: 5672 username: admin password: admin eureka: client: service-url: defaultZone: http://localhost:8761/eureka/
配置好後,將以上項目都重啓,而後到RabbitMQ上,能夠看到註冊上來的隊列:
確認都可以正常註冊到rabbitmq後,咱們到碼雲上,規範配置文件的名稱。修改以前的order.yml爲order-dev.yml,而且增長商品服務的配置文件,以下:
並在order-dev.yml文件裏,增長一段env配置:
完成配置文件的修改後,再到訂單服務項目裏,增長一個 EnvController 類,用來測試配置刷新是否正常。代碼以下:
package org.zero.springcloud.order.server.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @program: sell_order * @description: * @author: 01 * @create: 2018-08-20 23:17 **/ @RestController @RequestMapping("/env") @RefreshScope // 這個註解聲明瞭刷新配置的範圍,若是使用config配置類的話,就聲明到配置類上便可 public class EnvController { @Value("${env}") private String env; @GetMapping("/print") public String print(){ return env; } }
重啓訂單服務項目,訪問/env/print
接口,返回的結果以下:
這時,咱們再到碼雲上修改order-dev.yml文件裏的env配置爲beat,以下:
而後訪問bus用於刷新配置的接口:
稍等一會,控制檯應該會打印刷新日誌,接着再訪問以前的測試接口,返回beta則說明刷新是有效的。由於這個過程當中,咱們並無重啓訂單服務或配置中心服務:
到了本小節,就表明咱們已經成功集成了RabbitMQ以及Spring Cloud Bus進行配置文件的動態刷新,可是咱們目前依舊須要手動去訪問Bus用於刷新配置的接口,才能完成配置文件的動態刷新。咱們但願的是,當git倉庫的文件更新時就可以實現動態刷新配置文件。要實現這個功能就須要Git倉庫可以在配置文件更新後,自動調用Bus用於刷新配置的接口。那麼要怎麼實現這個功能呢?這就須要用到WebHooks了,好在碼雲和GitHub都支持WebHooks,咱們只須要配置一下接口地址便可。這也是咱們本小節須要演示的。
注:SpringCloud須要2.0.0以上的版本纔開始支持碼雲的WebHooks,低版本對碼雲的WebHooks不兼容
首先打開倉庫的管理界面,選擇WebHooks,並點擊右上角的添加:
而後輸入相應的配置信息,注意這裏不是配置/actuator/bus-refresh
接口了 ,而是配置 spring cloud config 裏特定給WebHooks調用的/monitor
接口。至於域名,我這裏使用了內網穿透的地址:
添加完成後,點擊右上角的測試,返回結果以下,則表明測試經過:
如今咱們用以前的order-dev.yml配置文件進行一個測試,把env的值改成test,以下:
而後在不重啓任何項目的狀況下,訪問以前打印env配置的接口。返回結果以下表明自定刷新成功了: