Spring Cloud學習筆記【九】配置中心Spring Cloud Config


Spring Cloud Config 是 Spring Cloud 團隊創建的一個全新項目,用來為分布式系統中的基礎設施和微服務應用提供集中化的外部配置支持,它分為服務端與客戶端兩個部分。其中服務端也稱為分布式配置中心,它是一個獨立的微服務應用,用來連接配置倉庫並為客戶端提供獲取配置信息、加密 / 解密信息等訪問接口;而客戶端則是微服務架構中的各個微服務應用或基礎設施,它們通過指定的配置中心來管理應用資源與業務相關的配置內容,並在啟動的時候從配置中心獲取和加載配置信息。Spring Cloud Config 實現了對服務端和客戶端中環境變量和屬性配置的抽象映射,所以它除了適用於 Spring 構建的應用程序之外,也可以在任何其他語言運行的應用程序中使用。由於 Spring Cloud Config 實現的配置中心默認采用 Git 來存儲配置信息,所以使用 Spring Cloud Config 構建的配置服務器,天然就支持對微服務應用配置信息的版本管理,並且可以通過 Git 客戶端工具來方便的管理和訪問配置內容。當然它也提供了對其他存儲方式的支持,比如:GIT倉庫、SVN 倉庫、本地化文件系統。

下面我們將構建一個基於 Git 存儲的分布式配置中心,並對客戶端進行改造,讓其能夠從配置中心獲取配置信息並綁定到代碼中。

准備工作

准備一個 Git 倉庫,在 Github 上面創建了一個文件夾 config-repo 用來存放配置文件,為了模擬生產環境,我們創建以下三個配置文件:

1 // 開發環境
2 config-server-dev.yml
3 // 測試環境
4 config-server-test.yml
5 // 生產環境
6 config-server-prod.yml

每個配置文件中都寫一個屬性 info.profile, 屬性值分別是 dev/test/prod

Server 端

創建一個基礎的 Spring Boot 工程,命名為:service-config-server

POM依賴

1 <dependency>
2     <groupId>org.springframework.cloud</groupId>
3     <artifactId>spring-cloud-config-server</artifactId>
4 </dependency>
5 <dependency>
6     <groupId>org.springframework.cloud</groupId>
7     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
8 </dependency>

配置文件

在 application.yml 中添加配置服務的基本信息以及 Git 倉庫的相關信息

server:
  port: 9300
spring:
  application:
    name: service-config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/carry-chan/spring-cloud # 配置git倉庫的地址
          search-paths: config-repo # git倉庫地址下的相對地址,可以配置多個,用,分割。
eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:123456@localhost:8761/eureka/

Spring Cloud Config 也提供本地存儲配置的方式。我們只需要設置屬性spring.profiles.active=native,Config Server會從默認的src/main/resource目錄下檢索配置文件。也可以通過spring.cloud.config.server.native.searchLocations=file:E:/properties/屬性來制定配置文件的位置。雖然 Spring Cloud Config 提供了這樣的功能,但是為了支持更好的管理內容和版本控制的功能,還是推薦使用 Git 的方式。

如果我們的 Git 倉庫需要權限訪問,那么可以通過配置下面的兩個屬性來實現
spring.cloud.config.server.git.username:訪問 Git 倉庫的用戶名
spring.cloud.config.server.git.password:訪問 Git 倉庫的用戶密碼

啟動類

 1 package com.carry.springcloud;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.config.server.EnableConfigServer;
 6 
 7 @EnableConfigServer
 8 @SpringBootApplication
 9 public class ServiceConfigServerApplication {
10 
11     public static void main(String[] args) {
12         SpringApplication.run(ServiceConfigServerApplication.class, args);
13     }
14 }

到此 Server 端相關配置已經完成。

測試

啟動eureka-server、service-config-server,瀏覽器直接訪問 http://localhost:9300/config-server/dev 返回信息如下:

{
    "name": "config-server",
    "profiles": [
    "dev"
    ],
    "label": null,
    "version": "beb220098b44c60cf99277f064a19d52e7ebeb91",
    "state": null,
    "propertySources": [
      {
        "name": "https://github.com/carry-chan/spring-cloud/config-repo/config-server-dev.yml",
       "source": {
         "info.profile": "dev"
         }
      }
    ]
}

 上述的返回的信息包含了配置文件的位置、版本、配置文件的名稱以及配置文件中的具體內容,說明 Server 端已經成功獲取了 Git 倉庫的配置信息。

如果直接查看配置文件中的配置信息可訪問 http://localhost:9300/config-server-dev.yml 返回:

info: 
  profile: dev

修改配置文件config-server-dev.yml中配置信息為dev v0,再次在瀏覽器訪問 http://localhost:9300/config-server-dev.yml 返回:dev v0,說明 Server 端會自動讀取最新提交的內容。

倉庫中的配置文件會被轉換成 Web 接口,訪問可以參照以下的規則:

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

上面的 URL 會映射 {application}-{profile}.yml 對應的配置文件,其中 {label} 對應 Git 上不同的分支,默認為 master。

Client 端

創建一個基礎的 Spring Boot 應用,命名為 service-config-client。

POM依賴

 1 <dependency>
 2       <groupId>org.springframework.boot</groupId>
 3       <artifactId>spring-boot-starter-webflux</artifactId>
 4 </dependency>
 5 <dependency>
 6       <groupId>org.springframework.cloud</groupId>
 7       <artifactId>spring-cloud-starter-config</artifactId>
 8 </dependency>
 9 <dependency>
10       <groupId>org.springframework.cloud</groupId>
11       <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
12 </dependency>

配置文件

需要配置兩個配置文件,application.yml 和 bootstrap.yml,配置分別如下:

application.yml

server:
  port: 9400
spring:
  application:
    name: service-config-client

bootstrap.yml

spring:
  cloud:
    config:
      name: config-server # 對應 {application} 部分
      profile: dev # 對應 {profile} 部分
      label: master # 對應 {label} 部分,即 Git 的分支。如果配置中心使用的是本地存儲,則該參數無用
      discovery:
        enabled: true
        service-id: service-config-server #springcloud config的服務名
eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:123456@localhost:8761/eureka/

注意:上面這些與 Spring Cloud Config 相關的屬性必須配置在 bootstrap.yml 中,config 部分內容才能被正確加載。因為 config 的相關配置會先於 application.yml,而 bootstrap.yml 的加載也是先於 application.yml。

啟動類

 1 package com.carry.springcloud;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 
 6 @SpringBootApplication
 7 public class ServiceConfigClientApplication {
 8 
 9     public static void main(String[] args) {
10         SpringApplication.run(ServiceConfigClientApplication.class, args);
11     }
12 }

在 Controller 中使用 @Value 注解來獲取 Server 端參數的值

 1 package com.carry.springcloud;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 import org.springframework.cloud.context.config.annotation.RefreshScope;
 5 import org.springframework.web.bind.annotation.GetMapping;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 import reactor.core.publisher.Mono;
 9 
10 @RestController
11 public class ClientController {
12 
13     @Value("${info.profile}")
14     private String profile;
15 
16     @GetMapping("/info")
17     public Mono<String> hello() {
18         return Mono.justOrEmpty(profile);
19     }
20 }

測試

依次啟動項目eureka-server、service-config-server、service-config-client,訪問 http://localhost:9400/info 返回dev 說明已經正確的從 Server 端獲取到了參數。

手動修改Git倉庫中 config-server-dev.yml 的值,再次訪問 http://localhost:9400/info 依舊返回dev,這是因為 Spring Cloud Config 分服務端和客戶端,服務端負責將 Git 中存儲的配置文件發布成 REST 接口,客戶端可以從服務端 REST 接口獲取配置。但客戶端並不能主動感知到配置的變化,從而主動去獲取新的配置。客戶端如何去主動獲取新的配置信息呢,Spring Cloud 已經給我們提供了解決方案,每個客戶端通過 POST 方法觸發各自的 /actuator/refresh。

Refresh功能

修改客戶端即 service-config-client 項目

添加依賴

1 <dependency>
2     <groupId>org.springframework.boot</groupId>
3     <artifactId>spring-boot-starter-actuator</artifactId>
4 </dependency>

增加了spring-boot-starter-actuator包,spring-boot-starter-actuator是一套監控的功能,可以監控程序在運行時狀態,其中就包括/actuator/refresh的功能。

開啟更新機制

需要給加載變量的類上面加 @RefreshScope,在客戶端執行/actuator/refresh的時候就會更新此類下面的變量值。

 1 package com.carry.springcloud;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 import org.springframework.cloud.context.config.annotation.RefreshScope;
 5 import org.springframework.web.bind.annotation.GetMapping;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 import reactor.core.publisher.Mono;
 9 
10 @RestController
11 @RefreshScope
12 public class ClientController {
13 
14     @Value("${info.profile}")
15     private String profile;
16 
17     @GetMapping("/info")
18     public Mono<String> hello() {
19         return Mono.justOrEmpty(profile);
20     }
21 }

配置

Spring Boot 1.5.X 以上默認開通了安全認證,所以要在配置文件 application.yml 中添加以下配置以將/actuator/refresh這個 Endpoint 暴露出來

management:
  endpoints:
    web:
      exposure:
        include: refresh

測試

重啟 service-config-client 項目

訪問 http://localhost:9400/info 返回dev

我將 Git 上對應配置文件里的值改為dev v0

執行 curl -X POST http://localhost:9400/actuator/refresh,返回["config.client.version","info.profile"]

再次訪問 http://localhost:9400/info 返回dev v0

這就說明客戶端已經得到了最新的值,Refresh 是有效的。

Webhook

現在雖然可以不用重啟服務就更新配置了,但還是需要我們手動操作,這樣還是不可取的。所以,這里就要用到git的webhooks來達到自動更新配置。

打開git上配置倉庫的地址,添加webhooks

上面的Payload URL就填寫我們的配置中心觸發刷新的地址,當然這里不能寫localhost,要外網訪問地址才行。還有這里面有個Secret的秘鑰驗證,如果這里填寫的話,在配置文件上要寫上encrypt.key與之對應。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM