1. 程式人生 > >SpringCloud進擊 | 七淺出:配置中心(Git配置與更新)【Finchley版本】

SpringCloud進擊 | 七淺出:配置中心(Git配置與更新)【Finchley版本】

1.前言

在本文,我們將構建一個基於 Git 版儲存的分散式配置中心,並對客戶端進行改造,其能夠從遠端配置中心獲取配置資訊,並繫結到程式碼中的 Spring Cloud Config 配置中心模組。

Spring Cloud Config

  • Spring Cloud 團隊建立的一個全新專案
  • 用來為分散式系統中的基礎設施和微服務應用提供集中化的外部配置支援,它分為服務端客戶端兩個部分
  • 實現了對服務端和客戶端中環境變數和屬性配置的抽象對映,所以它除了適用於 Spring 構建的應用程式之外,也可以在任何其他語言執行的應用程式中使用
  • 預設採用 Git 來儲存配置資訊,所以也支援對微服務應用配置資訊的版本管理,並且可以通過 Git 客戶端工具來方便的管理和訪問配置內容。當然它也提供了對其他儲存方式的支援,比如:SVN 倉庫、本地化檔案系統

配置中心服務端: 服務端也稱為分散式配置中心,它是一個獨立的微服務應用,用來連線配置倉庫併為客戶端提供獲取配置資訊、加密 / 解密資訊等訪問介面

配置中心客戶端: 客戶端則是微服務架構中的各個微服務應用或基礎設施,它們通過指定的配置中心來管理應用資源與業務相關的配置內容,並在啟動的時候從配置中心獲取和載入配置資訊

2.準備

開發環境config-client-dev.properties 配置如下:

config.tip=Demo for Spring Cloud config
config.env=dev

測試環境config-client-test.properties

配置如下:

config.tip=Demo for Spring Cloud config
config.env=test

生產環境config-client-prod.properties 配置如下:

config.tip=Demo for Spring Cloud config
config.env=prod

三個環境配置檔案的屬性基本一樣,config.env 屬性值分別是 dev、test、prod。

3.進擊

3.1.服務端(Config Service)

在專案上新建一個模組:wei-config-server,建立方法與第一節建立模組過程類似。但在Dependencies選擇依賴時需要注意,選擇左側的 Cloud Config 後,這裡需要鉤上 Config Server 項。

3.1.1.pom.xml依賴

pom依賴自動生成後,不用變動。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wei</groupId>
    <artifactId>wei-config-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>wei-config-server</name>
    <description>Demo project for Spring Boot</description>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.1.2.配置檔案

在 application.yml 中新增配置服務的基本資訊以及 Git 倉庫的相關資訊。

server:
  port: 8040
spring:
  application:
    name: wei-config-server
  cloud:
    config:
      label: master    # 對應 Git 上不同的分支,預設為 master
      server:
        git:
          username:
          password:
          uri: https://github.com/itanping/wei-springcloud     # 配置 Git 倉庫地址
          search-paths: wei-config/config-profile              # Git倉庫地址下的相對地址,可以配置多個,用,分割

如果 Git 倉庫需要許可權訪問,則需要配置下面的兩個屬性來實現(如果 Git 倉庫為公開倉庫,可以不填寫使用者名稱和密碼,如果是私有倉庫需要填寫,示例程式碼為公開倉庫,這裡配置了屬性項,但可以不用設定密碼):

  • spring.cloud.config.server.git.username:訪問 Git 倉庫的使用者名稱
  • spring.cloud.config.server.git.password:訪問 Git 倉庫的使用者密碼

3.1.3.啟動類

在該模組的啟動類上加上註解@EnableConfigServer,開啟對配置中心的支援。

package com.wei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

/**
 * Config Server
 * 註解@EnableConfigServer,開啟對配置中心的支援
 */
@SpringBootApplication
@EnableConfigServer
public class WeiConfigServerApplication {

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

好了,到此,Spring Cloud Config Server 端的相關配置已經完成。

3.1.4.測試

啟動模組 wei-config-server 的啟動類 WeiConfigServerApplication。

{     "name": "config-client",      "profiles": [         "dev"     ],      "label": null,      "version": "99d44110bcb18949e1cae5137eff5bc16cd74669",      "state": null,      "propertySources": [         {             "name": "https://github.com/itanping/wei-springcloud/wei-config/config-profile/config-client-dev.properties",              "source": {                 "config.tip": "Demo for Spring Cloud config",                  "config.env": "dev"             }         }     ] }

上面返回的資訊包含了配置檔案的名稱、位置、版本,以及配置檔案中的具體內容,說明 Config Server 端已經成功獲取到了 Git 倉庫的配置資訊。

瀏覽器正常列印了測試環境的配置檔案內容。試試生產環境,你會發現同樣的也會列印生產環境的配置檔案內容。

3.1.5.動態更新

修改配置檔案 config-client-dev.properties 中的屬性為 config.env=dev for update,以實現 Git 儲存與動態更新的讀取,如下:

config.tip=Demo for Spring Cloud config
config.env=dev for update

config.env: dev for update config.tip: Demo for Spring Cloud config

可以看到瀏覽器列印了更新後的開發環境配置內容,說明 Config Server 端會自動動態讀取 Git 最新提交的內容。

如此,Config Server 配置服務中心已經可以正常運作。

3.2.客戶端(Config Client)

在專案上新建一個模組:wei-config-client,建立方法與第一節建立模組過程類似。但在Dependencies選擇依賴時需要注意,選擇左側的 Cloud Config 後,這裡需要鉤上 Config Client 項。

3.2.1.pom.xml依賴

也是自動生成的 pom 依賴,這裡先不做修改。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wei</groupId>
    <artifactId>wei-config-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>wei-config-client</name>
    <description>Demo project for Spring Boot</description>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.2.2.配置檔案

如何在微服務應用中獲取上面服務端提供的配置資訊呢? 這裡我們新加一個配置檔案 bootstrap.yml。注意,一般情況下,application.yml 和 bootStrap.yml 在同一目錄下,這時 bootStrap.yml 的載入順序要高於 application.yml,即 bootStrap.yml 會優先被載入。

原理:

  • bootstrap.yml 用於應用程式上下文的引導階段。
  • bootstrap.yml 由父Spring ApplicationContext載入。
  • bootstrap.yml 可以理解成系統級別的一些引數配置,這些引數一般是不會變動的。
  • application.yml 可以用來定義應用級別的,如果搭配 spring-cloud-config 配置中心使用 application.yml,裡面定義的配置可以實現動態替換。

application.yml 配置

server:
  port: 8050

bootstrap.yml 配置

spring:
  application:
    name: wei-config-client
  cloud:
    config:
      uri: http://localhost:8040     # 配置服務中心的具體地址,即 config-server
      name: config-client            # 對應配置檔名 config-client-dev.properties 的 {application} 部分
      profile: dev                   # 對應配置檔名 config-client-dev.properties 的 {profile} 部分
      label: master                  # 使用 {label} 對應 Git 的分支名,如果配置中心使用的是本地儲存,則該引數無用

3.2.3.讀取配置

package com.wei.controller.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @Value("${config.env:config environment error}")
    private String configEnv;

    @Value("${config.tips:錯誤配置屬性config.tips測試,此處應該為config.tip}")
    private String configTip;

    @GetMapping("/demo/info")
    public String hello() {
        String result = "[Config Client] " + configEnv + ", " + configTip;
        return result;
    }
}

3.2.4.啟動類

package com.wei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WeiConfigClientApplication {

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

好了,到此,Spring Cloud Config Client 端的相關配置已經完成。

3.2.5.測試

啟動模組 wei-config-client 的啟動類 WeiConfigClientApplication。

[Config Client] dev for update, 錯誤配置屬性config.tips測試,此處應該為config.tip

如此,Config Client 從 Config Server 配置服務中心(Git倉庫)成功獲取到了開發環境配置項。

到此,Config Client 已經可以正常運作。

仔細的你,也許也已經發現,當使用Spring的@Value註解時,這裡設定了預設值。比如,config.tips 屬性在配置檔案中是沒有的,當編譯時,會提示找不到該屬性,如果使用@Value時設定了預設值,編譯就不會報錯,且請求返回的是其配置的預設值。

但是,這裡有個問題,上面的 Server 服務端可以獲取到配置變更後的最新內容,可是 Client 端不會,修改配置檔案 config-client-dev.properties 中的屬性後,獲取到的還是變更前的內容。

因為 Spring Cloud Config 分服務端和客戶端,服務端負責將 Git 中儲存的配置檔案釋出成 REST 介面,客戶端可以從服務端 REST 介面獲取配置。但客戶端並不能主動感知到配置的變化,從而主動去獲取新的配置。

要實現動客戶端的動態更新,請關注後面的章節。

4.總結

倉庫中的配置檔名會被轉換成 HTTP 介面,訪問可以參照以下規則:

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

上面的 URL 會對映 {application}-{profile}.properties 對應的配置檔案,其中 {label} 對應 Git 上不同的分支,預設為 master。以本節使用的 config-client-dev.properties 配置檔案為例,它的 application 是 config-client,profile 是 dev。

下一節,請繼續關注