Spring Cloud Config 高可用

                           Spring Cloud Config 高可用

高可用配置

當要將配置中心部署到生產環境中時,與服務註冊中心一樣,我們也希望它是一個高可用的應用。SpringCloudCoiifig實現服務端的高可用非常簡單,主要有以下兩種方式。

  • 傳統模式:不需要爲這些服務端做任何額外的配置,只需要遵守一個配置規則,將所有的Config Server都指向同一個Git倉庫,這樣所有的配置內容就通過統一的共享文件系統來維護。而客戶端在指定Config Server位置時,只需要配置Config Server上層的負載均衡設備地址即可,就如下圖所示的結構:

  • 服務模式:除了上面這種傳統的實現模式之外,我們也可以將Config Server作爲一個普通的微服務應用,納入Eureka的服務治理體系中。這樣我們的微服務應用就可以通過配置中心的服務名來獲取配置信息,這種方式比起傳統的實現模式來說更加有利於維護,因爲對於服務端的負載均衡配置和客戶端的配置中心指定都通過服務治理機制一併解決了,既實現了高可用,也實現了自維護。由於這部分的實現需要客戶端的配合,具體示例讀者可詳細閱讀“客戶端詳解”一節中的“服務化配置中心”小節 

客戶端詳解

在學習了關於Spring Cloud Config 服務端的大量配置和使用細節之後,接下來我們將通過下面的內容繼續學習Spring Cloud Config客戶端的使用與配置。

URI指定配置中心

      Spring Cloud Config 的客戶端在啓動的時候,默認從工程的classpath中加載配置信息並啓動應用,只有當我們配置spring.cloud .config.uri的時候,客戶端應用纔會嘗試連接Spring Cloud Config的服務端來獲取遠程配置信息並初始化Spring環境配置。同時,我們必須將該參數配置在bootstrap.propertie、環境變量或是其他優先級高於應用Jar包內的配置信息中,才能正確加載到遠程配置。若不指定spring.cloud.config.uri參數的話,Spring Cloud Config的客戶端會默認嘗試連接http://10.0.45.103:8080。

項目github地址:[email protected]:13849141963/spring-cloud.git

     在之前的快速入門示例中,我們就是以這種方式實現的,就如下面的配置,其中spring.application.name和spring.cloud.config.profile用於定位配置信息。

spring.application.name=springcloud-config-client
# 指明遠程倉庫的分支
spring.cloud.config.label=master
# dev開發環境配置文件   test測試環境    pro正式環境
spring.cloud.config.profile=dev
# 配置中心config-server的地址
#spring.cloud.config.uri=http://10.0.45.103:8080/

服務化配置中心

在前幾篇博客中,我們己經學會了如何構建服務註冊中心、如何發現與註冊服務。那麼Config Server是否也能以服務的方式註冊到服務中心,並被其他應用所發現來實現配置信息的獲取呢?答案是肯定的。在Spring Cloud中,我們也可以把Config Server視爲微服務架構中與其他業務服務一樣的一個基本單元。
下面,我們就來詳細介紹如何將Config Server註冊到服務中心,並通過服務發現來訪問Config Server並獲取Git倉庫中的配置信息。下面的內容將基於快速入門中實現的 springcloud-config-server和springcloud-config-client工程來進行改造實現。
服務端配置
1、在springcloud-config-server 的 pom.xml 中增加spring-cloud-starter-eureka,spring-cloud-config-server依賴,以實現將分佈式配置中心加入Eureka的服務治理體系。

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!--分佈式配置中心-->
    <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-config-server</artifactId>
   </dependency>

   <!--Eureka服務註冊中心-->
   <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
   </dependency>

   <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
   </dependencyManagement>

 2、在application.properties配置文件中配置參數eureka.client.service-url.defaultZone已指定服務註冊中心的位置,詳細內容如下:

spring.application.name=springcloud-config-server
server.port=8080
# 配置git倉庫地址
spring.cloud.config.server.git.uri=https://github.com/13849141963/spring-config-file/
# 配置倉庫的分支
spring.cloud.config.label=master
# 配置倉庫路下的相對搜索位置.可以配置多個
spring.cloud.config.server.git.search-paths=respoitory
# 訪問git倉庫的用戶名
spring.cloud.config.server.git.username=13849141963
# 訪問git倉庫的用戶密碼 如果Git倉庫爲公開倉庫,可以不填寫用戶名和密碼,如果是私有倉庫需要填寫
spring.cloud.config.server.git.password=********
#將分佈式配置中心交給eureka集羣註冊中心來管理
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer3:3333/eureka/,http://peer2:2222/eureka/
#雖然SpringCloudConfig提供這樣的功能,但是爲了支持更好的內容管理和版本控制等強大功能,還是推薦使用Git倉庫的方式
#不使用git倉庫或者svn倉庫的存儲方式   configSever會默認從應用的src/main/resources目錄下搜尋文件
#spring.profiles.active=native
#如果需要指定搜索配置文件的路徑,通過這個屬性來指定具體的配置文件位置
#spring.cloud.config.server.native.search-locations=文件位置

3、在應用主類中,新增@EnableDiscoveryClient註解,用來將springcloud-config-server應用註冊到上面的服務註冊中心上去。

//分佈式配置中心註解
@EnableConfigServer
//發現註冊中心
@EnableEurekaClient
@SpringBootApplication
public class SpringcloudConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudConfigServerApplication.class, args);
    }
}

 4、啓動該應用,並訪問eureka集羣http://10.0.45.103:1111,http://10.0.45.103:2222,http://10.0.45.103:3333,可以在Eureka Server的信息面板中看到springcloud-config-server已經被註冊了。

客戶端配置

1、在springcloud-config-client的pom.xml中新增spring-cloud-starter-eureka依賴,以實現客戶端發現springcloud-config-server服務,具體配置如下:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!--分佈式配置中心-->
    <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>

    <!--Eureka服務註冊中心-->
    <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

   <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2、在bootstrap.properties文件中,按如下配置:

spring.application.name=springcloud-config-client
# 指明遠程倉庫的分支
spring.cloud.config.label=master
# dev開發環境配置文件   test測試環境    pro正式環境
spring.cloud.config.profile=dev
# 配置中心config-server的地址 在configServer分佈式配置中心沒有在eureka註冊中心註冊時,指定該ConfigServer的服務器地址通過訪問Controller
# 來測試客戶端獲取git倉庫的某個文件內容,之後ConfigServer在註冊中心進行註冊就可以使用service-id屬性來指定分佈式服務的名稱,直接使用分佈式服務
#spring.cloud.config.uri=http://10.0.45.103:8080/
#端口
server.port=7001
#開啓通過服務來訪問ConfigServer的功能
spring.cloud.config.discovery.enabled=true
#指定分佈式配置中心服務名稱
spring.cloud.config.discovery.service-id=springcloud-config-server
#將分佈式配置中心交給eureka集羣註冊中心來管理
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer3:3333/eureka/,http://peer2:2222/eureka/
#關閉刷新安全認證
management.security.enabled=false
#和重試機制相關的配置有如下四個:
# 配置重試次數,默認爲6
spring.cloud.config.retry.max-attempts=6
# 間隔乘數,默認1.1
spring.cloud.config.retry.multiplier=1.1
# 初始重試間隔時間,默認1000ms
spring.cloud.config.retry.initial-interval=1000
# 最大間隔時間,默認2000ms
spring.cloud.config.retry.max-interval=2000

 其中,通過eureka.client.service-url.defaultZone參數指定服務註冊中心,用於服務註冊與發現;在將spring.cloud.config.discovery.enabled參數設置爲true,開啓通過服務來訪問Config Server的功能;最後利用spring.cloud.config.discovery.serviceId參數來指定Config Server註冊的服務名。這裏的spring.application.name和spring.cloud.config.profile如之前通過URI的方式訪問的時候一樣,用來定位Git中的資源。

3、在應用主類中,增加@EnableEurekaClient註解,用來發現springcloud-config-server服務,利用其來加載應用配置:

@SpringBootApplication
@EnableEurekaClient
public class SpringcloudConfigClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudConfigClientApplication.class, args);
    }
}

4、沿用之前我們創建的Controller來加載Git中的配置信息:

@RestController
public class TestGetConfigController {

    @Value("${configFile}")
    String configFile;

    @RequestMapping(value = "/configFile")
    public String getConfigFile(){
        return configFile;
    }
}

5、完成上述配置之後,我們啓動客戶端應用。若啓動成功,訪問http://10.0.45.103:7001/configFile,可以在Eureka Server的信息面板中看到該應用已經被註冊成功。

6、訪問客戶端應用提供的服務 http://10.0.45.103:7001/configFile,此時,我們會返回在Git倉庫中application-dev.properties文件中的配置config-filede屬性內容:“configFile dev version 1”

失敗快速響應與重試

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

       我們可以實現一下,在未配置該參數前,不啓動Config Server,直接啓動客戶端應用,可以獲得下面的報錯信息。同時,在報錯之前,可以看到客戶端應用加載了很多內容,比如說Controller的請求等。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testGetConfigController': Injection of autowired dependencies failed;

 加上spring.cloud.config.fail-fast=true 參數之後,在啓動客戶端應用,可以獲取下面的報錯信息,並且前置的加載內容少了很多,這樣通過該參數有效地避免的了當Congfig Server配置有誤時,不需要多等待前置的一些加載時間,實現了快速返回失敗信息

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

 上面我們演示了當Config Server宕機或是客戶端配置不正確導致連接不到而啓動失敗的情況,快速響應的配置可以發揮比較好的效果。但是,若只是因爲網絡波動等其他間接性原因導致的問題,直接啓動失敗似乎代價有點高。所以Config客戶端還提供了自動重試的功能,在開啓重試功能前,先確保已經配置了spring.cloud.config.failFast=true,在進行下面的操作。

1、在客戶端的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>

 2、不需要在做其他任何配置,啓動客戶端應用,在控制檯中可以看到如下內容。客戶端在連接Config Server失敗之後,會繼續嘗試,知道第六次失敗後才返回錯誤信息。通過這樣的重試機制,可以避免一些間歇性問題引起的失敗導致客戶端應用無法啓動的情況。

2018-11-06 14:14:50.752  INFO 828 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2018-11-06 14:14:52.813  INFO 828 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2018-11-06 14:14:54.947  INFO 828 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2018-11-06 14:14:57.188  INFO 828 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2018-11-06 14:14:59.548  INFO 828 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2018-11-06 14:15:02.044  INFO 828 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2018-11-06 14:15:03.084 ERROR 828 --- [           main] o.s.boot.SpringApplication               : Application startup failed
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing

若對默認的最大重試次數和重試間隔等設置不滿意,還可以通過下面的參數進行調整。

spring.cloud.config.retry.multiplier:初始重試間隔時間(單位爲毫秒),默認爲1000毫秒。
spring.cloud.config.retry.initial-interval:下一間隔的乘數,默認爲1.1所以當初間隔是1000毫秒時,下一次失敗的間隔爲1100毫秒。
spring.cloud.config.retry.max-interval:最大間隔時間,默認爲2000毫秒。
spring.cloud.config.retry.max.attempts:最大重試次數,默認爲六次。

獲取遠程配置

       在入門示例中,我們隊{application}、{profile}、{lable}這些參數已經有了一定的瞭解。在Git倉庫中,一個形如{application}-{profile}.properties或{application}-{profile}.yml的配置文件,通過URL請求和客戶端配置的訪問對應可以總結如下:

1、通過向Config Server發送GET請求以直接的方式獲取,可用下面的鏈接形式。 

 不帶{label}分支信息,默認訪問master分支,可使用:
   1./{application}-{profile}.yml
   2./{application}-{profile}-properties
 帶{label}分支信息,可使用:
   1./{label}/{application}-{profile}.yml
   2./{application}/{profile}[/{label}]
   3./{label}/{application}-{profile}.properties

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

 1.spring• application.name:對應配置文件中的{application}內容。
 2.spring. cloud, config.profile:對應配置文件中{profile}內容。
 3.spring.cloud.config. label:對應分支內容,如不配置,默認爲master。

動態刷新配置

       有時候,我們需要對配置內容做一些實時更新,那麼Spring Cloud Config是否可以實現呢?答案顯然是可以的。下面,我們以快速入門中的示例作爲基礎,看看如何進行改造來實現配置內容的實時更新。
       首先,回顧一下,當前我們已經實現了哪些內容。
       1、config-repo:定義在 Git倉庫中的一個目錄,其中存儲了應用名爲didispace的多環境配置文件,配置文件中有一個from參數。

       2、 config-server:配置了 Git倉庫的服務端。
       3、config- client:指定了springcloud-config-server爲配置中心的客戶端,應用名爲springcloud-config-client,用來訪問配置服務器以獲取配置信息。該應用中提供了一個/configFile接口,它會獲取 respository/ application-dev.properties 中的 configFile屬性返回。
       在改造程序之前,我們先將 springcloud-config- server 和 springcloud-config-client 都啓動起來,並訪問客戶端提供的REST接口 http:// localhost:7002/ configFile 來獲取配置信息,獲得的返回內容爲 configFile dev version 1。接着,我們可以嘗試使用Git工具修改當前配置的內容,比如, 將 respository/application-dev.properties 中的 configFile 的值從 configFile = configFile dev version 1 修改爲 configFile = configFile dev version 2,再訪問 http://10.0.45.103:7001/configFile,可以看到其返回內容還是configFile dev version 1。

       接下來,我們將在springcloud-config-client端做一些改造以實現配置信息的動態刷新。

 1、在springcloud-config-client的pom.xml中新增 spring-boot-starter-actuator 監控模塊。其中包含了/refresh端點的實現,該端點將用於應用配置信息的重新獲取與刷新。

  <!--實時刷新配置文件-->
  <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>

2、重新啓動 springcloud-config-client,訪問一次 http://10.0.45.103:7001/configFile 可以看到當前的配置值。

3、修改Git 倉庫 respository/application-dev.properties文件中的值。

4、在訪問一次 http://10.0.45.103:7001/configFile ,可以看到配置值沒有發生改變。

5、通過POST請求發送到 http://10.0.45.103:7001/refresh,我們可以看到返回內容如下,代表configFile參數的配置內容被更新了:

6、再一次訪問 http://10.0.45.103:7001/configFile,可以看到配置值已經是更新後的值了。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章