1. 程式人生 > >Spring Cloud系列(三十)Config客戶端—Finchley版本

Spring Cloud系列(三十)Config客戶端—Finchley版本

URI指定配置中心

Spring Cloud Config客戶端在啟動的時候,預設會從工程的classpath中載入配置資訊並啟動應用。只有當我們配置spring.cloud.config.uri的時候,客戶端才會嘗試連線Spring Cloud Config 的服務端來獲取遠端配置資訊並初始化Spring 環境配置。同時,我們必須將該引數配置在bootstrap.properties或者bootstrap.yml、環境變數或是其他優先順序高於應用jar包內的配置資訊中,才能正確載入到遠端配置。若不指定 spring.cloud.config.uri 引數的話,Spring Cloud Config 客戶端會預設嘗試連線http://localhost:8888。

spring:
  application:
    name: repo #要獲取的應用名
  cloud:
    config:
      uri: http://localhost:5666/ # 配置服務中心的地址
      label: master #要獲取的分支名
      profile: dev  #要獲取的環境名

服務化配置中心

Config Server 和 Config Client 也能以服務的方式註冊到服務中心,通過這種方式還可以實現配置中心的高可用,具體實現參考《Spring Cloud系列(二十九)高可用配置中心—Finchley版本》。

失敗快速響應與重試

Spring Cloud Config 的客戶端會遇見載入很多其他資訊,然後再開始連線Config Server進行屬性的注入。當我們構建的應用比較複雜的時候,可能在連線Config Server之前花費較長的啟動時間,而在一些特性場景下,我們又希望可以快速知道當前應用是否能順利地從Config Server獲取到配置資訊。這對在初期構建除錯環境中,可以減少很多等待啟動的時間。要實現客戶端優先判斷Config Sever獲取是否正常,並快速響應失敗內容,只需要在bootstrap檔案中配置引數spring.cloud.config.failFast=true即可。

加上spring.cloud.config.failFast=true

後,再啟動客戶端時,如果Config Server無法正常工作時,會直接報錯無法啟動。並快速返回失敗資訊。

java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing

上面演示了當Config Server宕機或者是客戶端配置不正確導致連線不到而啟動失敗的情況,快速響應的配置可以發揮比較好的效果。但是若只是因為網路波動等其他間歇性原因導致的問題,直接啟動失敗似乎代價太高了。所以,Config 客戶端還提供了自動重試的功能,在開啟重試功能之前要確保spring.cloud.config.failFast=true

在客戶端的pom.xml中引入spring-retry和spring-boot-starter-aop依賴。

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

不需要做任何配置,啟動客戶端,在控制檯看到如下內容。客戶端在連線Config Server失敗後,會繼續嘗試,直到第6次失敗後採訪錯誤資訊。通過這樣的重試機制可以避免一些間歇性問題引起的失敗導致客戶端應用無法啟動的情況。

2018-09-30 10:46:32.409  INFO 13248 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:34.865  INFO 13248 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:36.962  INFO 13248 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:39.555  INFO 13248 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:42.015  INFO 13248 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:44.502  INFO 13248 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:45.555 ERROR 13248 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing

當然你也可以通過如下引數調整重試次數和重試間隔。

  • spring.cloud.config.retry.max-attempts:最大重試次數,預設6次。
  • spring.cloud.config.retry.max-interval:最大間隔時間,預設2000毫秒。
  • spring.cloud.config.retry.multiplier:初始重試間隔時間,單位毫秒,預設1000毫秒。
  • spring.cloud.config.retry.initial-interval:下一間隔的乘數,預設為1.1,所以當最初間隔是1000毫秒時,下一次失敗後的間隔為1100毫秒。

獲取遠端配置

在之前的介紹中,已經對{application}{profile}{label}這些引數有了一定的瞭解。在Git倉庫中,一個形如{application}-{profile}.properties或者{application}-{profile}.yml的配置檔案,通過URL請求和客戶端配置的訪問對應可以總結如下:

通過向Config Server傳送Get請求以直接的方式獲取,可用下面的連結形式。

不帶{label}分支資訊,預設訪問master分支,可使用:

  • /{application}-{profile}.properties
  • /{application}-{profile}.yml

帶{label}分支資訊,可使用:

  • /{label}/{application}-{profile}.properties
  • /{label}/{application}-{profile}.yml
  • /{application}/{profile}/{label}

通過客戶端配置方式載入的內容如下所示。

  • spring.cloud.config.name:對應配置檔案中的{application}內容,如果沒有配置spring.cloud.config.name則去找spring.application.name。
  • spring.cloud.config.profile:對應配置檔案中的{profile}內容
  • spring.cloud.config.label:對應配置檔案中的{label}內容,如不配置預設為master。
spring:
  cloud:
    config:
      name: repo #對應application
      uri: http://localhost:5666/ # 配置服務中心的地址
      label: master #要獲取的分支名
      profile: dev  #要獲取的環境名

動態重新整理配置

有時候,我們需要對配置內容做一些實時更新的場景,那麼Spring Cloud Config是否可以實現呢?答案顯然是可以的。下面,我們看看如何進行改造來實現配置內容的實時更新。

在改造程式之前,我們先將config-server和config-client都啟動起來,並訪問客戶端提供的REST API http://localhost:5777/test1來獲取配置資訊,可以獲得返回內容為:git-dev-1.0-update。接著,我們可以嘗試使用Git工具修改當前配置的內容,比如,將config-repo/repo-dev.properties中的form的值從form=git-dev-1.0-update修改為form=git-dev-2.0-update,再訪問http://localhost:5777/test1,可以看到其返回內容還是git-dev-1.0-update。

下面,我們將在config-client端增加一些內容和操作以實現配置的重新整理:

第一步,在config-client的pom.xml中新增spring-boot-starter-actuator監控模組,其中包含了/actuator/refresh重新整理API。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

第二步,暴露refresh端點。

management:
  endpoints: 
    web:
      exposure:
        include: refresh

這裡寫"*"報錯,說有重複的端點,還沒找到原因。

第三步,確認REST Controller添加了@RefreshScope註解

@RefreshScope
@RestController
public class TestController {
    。。。
}

重新啟動config-client,訪問一次http://localhost:5777/test1,可以看到當前的配置值 修改Git倉庫config-repo/didispace-dev.properties檔案中form的值 再次訪問一次http://localhost:5777/test1,可以看到配置值沒有改變 通過POST請求傳送到http://localhost:5777/actuator/refresh,我們可以看到返回內容如下,代表form引數的配置內容被更新了

[
  "form"
]

再次訪問一次http://localhost:7002/from,可以看到配置值已經是更新後的值了。

注: @RefreshScope 開啟 SpringCloudConfig 客戶端的 refresh 重新整理範圍,來獲取服務端的最新配置,@RefreshScope要加在宣告@Controller宣告的類上,否則refresh之後Conroller拿不到最新的值,會預設呼叫快取。

通過上面的介紹,大家不難想到,該功能還可以同Git倉庫的Web Hook功能進行關聯,當有Git提交變化時,就給對應的配置主機發送/actuator/refresh請求來實現配置資訊的實時更新。但是,當我們的系統發展壯大之後,維護這樣的重新整理清單也將成為一個非常大的負擔,而且很容易犯錯,那麼有什麼辦法可以解決這個複雜度呢?後續我們將繼續介紹如何通過Spring Cloud Bus來實現以訊息匯流排的方式進行通知配置資訊的變化,完成叢集上的自動化更新。