原理
在Horizon平台的設計之初我們就引入了Spring Cloud Bus用於支撐配置的動態刷新。這項技術是基於消息隊列服務來實現的,簡單來說,Spring Cloud Bus使用一個消息隊列服務形成一個消息總線,每個需要獲取配置的客戶端都將與消息總線連接,獲得各自獨立的一個Channel,而配置中心則是負責通過消息總線通知所有客戶端獲取最新的配置。大致是如下這么個流向:
這里由於配置中心需要通知所有客戶端最新配置,因此,配置中心還需要從注冊中心獲取注冊服務的詳情。
而之所以使用消息隊列服務是因為,消息隊列服務本身支持“發布”–“訂閱”模式,在配置中心發布新配置后,將把這個動作廣播給所有的訂閱者,從而通知他們執行配置更新。
配置
我們這里沒有選擇Kafka,而是選擇了RabbitMQ,是出於如下考慮:
1、Kafka依賴zookeeper,而rabbitmq可以獨立部署
2、Kafka雖然吞吐量較RabbitMQ更大,但RabbitMQ的單一消息可靠性比Kafka更高。
3、由於配置刷新是吞吐量非常低的操作,可靠性>性能
在每一個客戶端都配置了消息總線的地址,並且引入了Spring-Cloud-Config-Client的依賴之后,每個客戶端都會與消息總線建立起如下連接:
同樣地,配置中心本身也需要實現一個動態刷新,但具體要實現的不是動態刷新功能,而是向外界暴露一個動態刷新的入口,這樣,可以在配置變更之后第一時間來調用這個接口完成刷新。這個接口已經預先定義好了,需要在Spring Boot Actuator中暴露一些端點:
management: endpoints: web: exposure: include: bus-refresh,bus-env,health,info
需要暴露出的是/bus-refresh和/bus-env兩個端點。在暴露之后,通過HTTP POST來調用如下端點:
http://127.0.0.1:7011/actuator/bus-refresh
當然,在調用時需要按照實際場景加上身份驗證信息。
實踐
來看看我們調用這個端點執行刷新之后會發生什么吧。
在9點44分我們修改了zuul-service的配置並執行了端點調用:
服務器返回了一個204的狀態碼,表示成功,但無需返回任何內容。
來看日志中心中的內容:
zuul-service立即開始進行配置重載,而且配置重載的速度非常快,兩台服務器的zuul-service分別花了1.273秒和3.357秒完成重載,並且,在后面的日志中,可以看到詳細的配置被刷新的記錄:
簡單敘述一下觸發端點之后客戶端的動作:
1、客戶端接收到消息總線下發的消息,從配置中心重新獲取配置
2、熱加載配置
3、重新注冊自身服務到注冊中心
小結
之所以引入這個配置熱刷新的機制,仍然是為了減少運維的工作量。如果沒有這個配置熱刷新的功能,每一個服務的配置變更后,運維人員都要登錄對應的服務器來手動停止並重新啟動服務,不僅耗費人力,也降低了服務穩定性。通過這種熱刷新機制,通過調用配置中心的端點就可以實現對所有服務配置的自動刷新,在配置有較大修改的時候可以極大省去運維工作。除此之外,也可以與BitBucket等Git倉庫進行WebHook集成,實現配置提交/合並時就自動刷新,進一步解放雙手,提升生產力。