微服務之分散式配置中心

aoho發表於2019-02-25

1. 分散式配置中心

分散式系統中,服務數量劇增,其配置檔案需要實現統一管理並且能夠實時更新,分散式配置中心元件必然是需要的。Spring Cloud提供了配置中心元件Spring Cloud Config ,它支援配置服務放在遠端Git倉庫和本地檔案中。預設採用git來儲存配置資訊,筆者示例也是採用預設的git repository,這樣通過git客戶端工具來方便的管理和訪問配置內容。

配置伺服器工作示意圖
配置伺服器工作示意圖

在Spring Cloud Config 元件中,有兩個角色,一是Config Server配置伺服器,為其他服務提供配置檔案資訊;另一個是Config Client即其他服務,啟動時從Config Server拉取配置。
下面分別介紹下Config Server和Config Client的搭建實現方法。

2. 配置伺服器Config Server

2.1 pom中的jars

只需要新增如下兩個jar包的引用。

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>jsr311-api</artifactId>
                    <groupId>javax.ws.rs</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>複製程式碼

因為Spring Cloud Config伺服器為客戶端提供配置是要通過服務發現,所以這邊引入consul的starter,配置伺服器和客戶端都註冊到consul叢集中。

2.2 入口類

簡單,因為Spring Cloud 提供了很多開箱即用的功能,通過spring-cloud-config-server的註解啟用配置伺服器。

@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}複製程式碼

@EnableConfigServer註解很重要,將該服務標註為配置伺服器;@EnableDiscoveryClient註冊服務,供其他服務發現呼叫。

2.3 bootstrap.yml

server:
  port: 8888

spring:
  application:
    name: config-server
  cloud:
      consul:
        discovery:
          preferIpAddress: true
          enabled: true
          register: true
          service-name: config-service
          //...
        host: localhost
        port: 8500
---
spring:
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/keets/Config-Repo.git
          searchPaths: ${APP_LOCATE:dev}
          username: user
          password: pwd複製程式碼

配置第一段指定了服務的埠;第二段是服務發現相關的配置;第三段是配置伺服器的資訊,這裡將配置檔案儲存在碼雲上,預設的搜尋檔案路徑為dev資料夾,可以通過環境變數指定,再下面是使用者名稱和密碼,公開的專案不需要設定使用者名稱和密碼。

至此配置伺服器已經搭建完成,是不是很簡單?

3. 配置的git倉庫

配置伺服器配置的倉庫是https://gitee.com/keets/Config-Repo.git。筆者在這個倉庫中建了兩個資料夾:dev和prod。並且在dev資料夾中新建了檔案configclient-dev.yml。為什麼這樣命名,能隨便命名嗎?答案是不可以,下面我們看下config檔案的命名規則。

URL與配置檔案的對映關係如下:

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties
    上面的url會對映{application}-{profile}.yml對應的配置檔案,{label}對應git上不同的分支,預設為master
    比如Config Client,{application}對應spring.application:configclient,exp對應{profile},{label}不指定則預設為master。

新建的configclient-dev.yml如下:

spring:
  profiles: dev

cloud:
  version: Dalston.SR4複製程式碼

4. 配置客戶端Config Client

4.1 pom中的jars

只需要新增如下兩個jar包的引用。

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>jsr311-api</artifactId>
                    <groupId>javax.ws.rs</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>複製程式碼

新增spring-boot-starter-actuator監控模組,為了配置資訊是動態重新整理,其中包含了/refresh重新整理API。其他和配置伺服器中新增的相同,沒啥可說。

4.2 入口類

簡單,因為Spring Cloud 提供了很多開箱即用的功能,通過spring-cloud-config-server的註解啟用配置伺服器。

@SpringBootApplication
@EnableDiscoveryClient
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}複製程式碼

配置客戶端不需要@EnableConfigServer註解。

4.3 bootstrap.yml


server:
  port: 9901
cloud:
  version: Brixton SR7

spring:
  cloud:
    consul:
      discovery:
        preferIpAddress: true
        enabled: true
        register: true
        service-name: config-client
      //...
      host: localhost
      port: 8500

---
spring:
  profiles:
    active: dev
  application:
      #app名稱
    name: configclient
  cloud:
    config:
      #指定profile
      profile: dev
      label: master
      discovery:
        enabled: true
        #server名
        service-id: config-service
      enabled: true
      fail-fast: true

---
spring:
  profiles: default
  application:
    name: configclient複製程式碼

從上面配置可以看出我們所啟用的profile是dev,配置的配置服務名為config-service,指定從master分支拉取配置。所以configclient啟動時會去配置伺服器中拉取對應的configclient-dev的配置檔案資訊。

4.4 TestResource

筆者新建了一個TestResource,對應的API端點為/api/test。

    @Value("${cloud.version}")
    private String version;

    @GetMapping("/test")
    public String from() {
        return version;
    }複製程式碼

cloud.version可以在上面的配置檔案看到預設指定的是Brixton SR7,而筆者在配置中心設定的值為Dalston.SR4。

5. 測試結果

5.1 獲取配置

首先看一下配置客戶端啟動時的日誌資訊,是不是真的按照我們配置的,從配置伺服器拉取configclient-dev資訊。

ccstart
ccstart

從日誌看來,是符合的上面的配置猜想的。我們再從配置客戶端提供的API介面進一步驗證。

pj
pj

可以看到確實是Dalston.SR4,配置服務能夠正常執行。

5.2 動態重新整理配置

Spring Cloud Config還可以實現動態更新配置的功能。下面我們修改下Config Repo中的cloud.version配置為Camden SR7,並通過重新整理config client的/refresh端點來應用配置。
從下圖可以看到結果是預期所想。

rr
rr

這邊配置的重新整理是通過手工完成了,還可以利用githook進行觸發。當本地提交程式碼到git後,呼叫了下圖設定的url。有兩個端點可以使用:

  • refresh:以post方式執行/refresh 會重新整理env中的配置
  • restart:如果配置資訊已經注入到bean中,由於bean是單例的,不會去載入修改後的配置
    需要通過post方式去執行/restart, 還需要配置endpoints.restart.enabled: true。

第二種情況比較耗時,@RefreshScope是spring cloud提供的註解,在執行refresh時會重新整理bean中變數值。下面看一下原始碼上的解釋。

Convenience annotation to put a @Bean definition in RefreshScope.
Beans annotated this way can be refreshed at runtime and any components that are using them will get a new instance on the next method call, fully initialized and injected with all dependencies.

上面大意是RefreshScope是一個方便的bean註解,加上這個註解可以在執行態重新整理bean。其他使用該bean的components下次呼叫時會獲取一個被初始化好的新例項物件。

githook設定頁面如下。

githook
githook

6. 總結

本文主要講了配置伺服器和配置客戶端的搭建過程,最後通過配置客戶端的日誌和端點資訊驗證是否能成功使用配置服務中心。總體來說,非常簡單。文中的部分配置沒有寫完整,讀者需要可以看文末的git專案。

不過關於配置中心,本文的講解並不完整,下一篇文章將會講解配置伺服器與訊息匯流排的結合使用,實現對配置客戶端的自動更新及灰度釋出等功能。

本文原始碼
github: github.com/keets2012/S…
gitee: gitee.com/keets/sprin…

訂閱最新文章,歡迎關注我的公眾號

微信公眾號
微信公眾號


參考

  1. Spring Cloud Config
  2. 分散式配置中心

相關文章