Spring Cloud 系列之 Consul 配置中心

前面我們已經學習過 Spring Cloud Config 了:

它提供了配置中心的功能,但是需要配合 git、svn 或外部存儲(例如各種數據庫),且需要配合 Spring Cloud Bus 《Spring Cloud 系列之 Bus 消息總線》實現配置刷新。

前面的課程中我們也學習了 Spring Cloud Consul,當時講解了它作為註冊中心的使用方案,且作為 Spring Cloud 官方推薦替換 Eureka 註冊中心的方案。既然使用了 Consul,就可以使用 Consul 提供的配置中心功能,並且不需要額外的 git 、svn、數據庫等配合,且無需配合 Bus 即可實現配置刷新。

Spring Cloud 官方聲明 Consul 可以作為 Spring Cloud Config 配置中心的替代方案。

官方文檔://cloud.spring.io/spring-cloud-static/spring-cloud-consul/2.2.2.RELEASE/reference/html/#spring-cloud-consul-config

關於 Consul 註冊中心部分我們已經學習過,未學習的同學請參考之前的課程進行學習。今天我們主要講解 Consul 作為配置中心如何使用。

Consul 介紹

Consul 是 HashiCorp 公司推出的開源工具,用於實現分佈式系統的服務發現與配置。與其它分佈式服務註冊與發現的方案,Consul 的方案更「一站式」,內置了服務註冊與發現框架、分佈式一致性協議實現、健康檢查、Key/Value 存儲(配置中心)、多數據中心方案,不再需要依賴其它工具(比如 ZooKeeper 等),使用起來也較為簡單。

Consul 使用 Go 語言編寫,因此具有天然可移植性(支持Linux、Windows 和 Mac OS);安裝包僅包含一個可執行文件,方便部署,與 Docker 等輕量級容器可無縫配合。

Consul 特性

  • Raft 算法

  • 服務發現

  • 健康檢查

  • Key/Value 存儲(配置中心)

  • 多數據中心

  • 支持 http 和 dns 協議接口

  • 官方提供 Web 管理界面

Consul 安裝

點擊鏈接觀看:Consul 安裝視頻(獲取更多請關注公眾號「哈嘍沃德先生」)

Consul 是用 go 語言編寫的第三方工具需要單獨安裝使用。

下載

訪問 Consul 官網://www.consul.io 下載 Consul 的最新版本。

支持多種環境安裝,截圖中只顯示了部分環境。

安裝

單節點和集群的安裝方式在之前的課程中已經詳細講解過,這裡主要講解 Consul 配置中心的作用,我們在 Windows 安裝一個單節點的 Consul 即可。

下載後的壓縮包中就只有一個 consul.exe 的執行文件。

cd 到對應的目錄下,使用 cmd 啟動 Consul

# -dev表示開發模式運行
consul agent -dev -client=0.0.0.0

為了方便啟動,也可以在 consul.exe 同級目錄下創建一個腳本來啟動,腳本內容如下:

consul agent -dev -client=0.0.0.0
pause

訪問管理後台://localhost:8500/ 看到下圖意味着我們的 Consul 服務啟動成功了。

初始化配置

點擊鏈接觀看:初始化配置信息視頻(獲取更多請關注公眾號「哈嘍沃德先生」)

創建基本目錄

使用 Consul 作為配置中心,第一步我們先創建目錄,把配置信息存儲至 Consul。

點擊菜單 Key/Value 再點擊 Create 按鈕。

創建 config/ 基本目錄,可以理解為配置文件所在的最外層文件夾。

創建應用目錄

點擊 config 進入文件夾。

再點擊 Create 按鈕。

創建 orderService/ 應用目錄,存儲對應微服務應用的 default 環境配置信息。

多環境應用目錄

假設我們的項目有多環境:defaulttestdevprod,在 config 目錄下創建多環境目錄。

  • orderService 文件夾對應 default 環境
  • orderService-test 文件夾對應 test 環境
  • orderService-dev 文件夾對應 dev 環境
  • orderService-prod 文件夾對應 prod 環境

初始化配置

dev 環境為例,點擊 orderService-dev 進入文件夾。

點擊 Create 按鈕準備創建 Key/Value 配置信息。

填寫 Key:orderServiceConfig

填寫 Value:

name: order-service-dev
mysql:
  host: localhost
  port: 3006
  username: root
  password: root

假設以上內容為訂單微服務的配置信息,下面我們通過案例來加載 Consul 配置中心中的配置信息。

環境準備

consul-config-demo 聚合工程。SpringBoot 2.2.4.RELEASESpring Cloud Hoxton.SR1

  • order-service:訂單服務
  • order-service02:訂單服務

實踐案例

點擊鏈接觀看:Consul 配置中心實踐視頻(獲取更多請關注公眾號「哈嘍沃德先生」)

添加依賴

需要從 Consul 獲取配置信息的項目主要添加 spring-cloud-starter-consul-config 依賴,完整依賴如下:

order-serviceorder-service02 依賴一致。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>order-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 繼承父依賴 -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>consul-config-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- 項目依賴 -->
    <dependencies>
        <!-- spring boot web 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring boot actuator 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- spring cloud consul discovery 服務發現依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- spring cloud consul config 配置中心依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>

        <!-- spring boot test 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

</project>

配置文件

老規矩,配置文件必須叫 bootstrap.yml 我們除了使用 Consul 配置中心功能之外,把微服務也註冊到 Consul 註冊中心去。order-serviceorder-service02 的配置項中除了端口和註冊實例 id 之外,其餘配置項一致,完整配置如下:

server:
  port: 9090 # 端口

spring:
  application:
    name: order-service # 應用名稱
  profiles:
    active: dev # 指定環境,默認加載 default 環境
  cloud:
    consul:
      # Consul 服務器地址
      host: localhost
      port: 8500
      # 配置中心相關配置
      config:
        # 是否啟用配置中心,默認值 true 開啟
        enabled: true
        # 設置配置的基本文件夾,默認值 config 可以理解為配置文件所在的最外層文件夾
        prefix: config
        # 設置應用的文件夾名稱,默認值 application 一般建議設置為微服務應用名稱
        default-context: orderService
        # 配置環境分隔符,默認值 "," 和 default-context 配置項搭配
        # 例如應用 orderService 分別有環境 default、dev、test、prod
        # 只需在 config 文件夾下創建 orderService、orderService-dev、orderService-test、orderService-prod 文件夾即可
        profile-separator: '-'
        # 指定配置格式為 yaml
        format: YAML
        # Consul 的 Key/Values 中的 Key,Value 對應整個配置文件
        data-key: orderServiceConfig
        # 以上配置可以理解為:加載 config/orderService/ 文件夾下 Key 為 orderServiceConfig 的 Value 對應的配置信息
        watch:
          # 是否開啟自動刷新,默認值 true 開啟
          enabled: true
          # 刷新頻率,單位:毫秒,默認值 1000
          delay: 1000
      # 服務發現相關配置
      discovery:
        register: true                                # 是否需要註冊
        instance-id: ${spring.application.name}-01    # 註冊實例 id(必須唯一)
        service-name: ${spring.application.name}      # 服務名稱
        port: ${server.port}                          # 服務端口
        prefer-ip-address: true                       # 是否使用 ip 地址註冊
        ip-address: ${spring.cloud.client.ip-address} # 服務請求 ip

配置文件實體類

order-serviceorder-service02 實體類代碼一致。

package com.example.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "mysql")
public class MySQLProperties {

    private String host;
    private Integer port;
    private String username;
    private String password;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

控制層

order-serviceorder-service02 控制層代碼一致。

注意需要添加 @RefreshScope 註解用於重新刷新作用域實現屬性值自動刷新。

package com.example.controller;

import com.example.config.MySQLProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
public class ConfigController {

    @Autowired
    private MySQLProperties mySQLProperties;

    @Value("${name}")
    private String name;

    @GetMapping("/name")
    public String getName() {
        return name;
    }

    @GetMapping("/mysql")
    public MySQLProperties getMySQLProperties() {
        return mySQLProperties;
    }

}

啟動類

order-serviceorder-service02 啟動類代碼一致。

package com.example;

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

@SpringBootApplication
public class OrderServiceApplication {

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

}

測試

修改配置信息前

訪問://localhost:9090/name 結果如下:

訪問://localhost:9090/mysql 結果如下:

修改配置信息

修改 Consul 配置中心 orderService-dev 環境的配置信息為:

name: order-service-dev-2.0
mysql:
  host: localhost
  port: 3006
  username: root123
  password: root123

修改配置信息後

控制台打印信息如下:

[TaskScheduler-1] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-config/order-service-dev/'}, BootstrapPropertySource {name='bootstrapProperties-config/order-service/'}, BootstrapPropertySource {name='bootstrapProperties-config/orderService-dev/'}, BootstrapPropertySource {name='bootstrapProperties-config/orderService/'}]
[TaskScheduler-1] o.s.boot.SpringApplication               : The following profiles are active: dev
[TaskScheduler-1] o.s.boot.SpringApplication               : Started application in 3.748 seconds (JVM running for 142.28)
[TaskScheduler-1] o.s.c.e.event.RefreshEventListener       : Refresh keys changed: [name, mysql.password, mysql.username]

Consul 使用 Spring 定時任務 Spring TaskScheduler來監聽配置文件的更新。

默認情況下,它是一個定時任務線程池 ThreadPoolTaskScheduler,其poolSize值為 1。要更改TaskScheduler,請創建一個 TaskScheduler 使用 ConsulConfigAutoConfiguration.CONFIG_WATCH_TASK_SCHEDULER_NAME 常量命名的 bean 類型。

訪問://localhost:9090/name 結果如下:

訪問://localhost:9090/mysql 結果如下:

總結

HashiCorp 公司的 Consul 可謂是一款全能組件。可用於提供服務發現和服務配置的工具。用 go 語言開發,具有很好的可移植性,被 Spring Cloud 納入其中。

在註冊中心方面,Netflix Eureka 停止新版本開發,Consul 成為了優秀的可替代方案。

在配置中心方面,Consul 亦可替代 Spring Cloud Config 作為配置中心使用,且無需配合 Git、SVN 等工具,無需配合 Bus 消息總線即可實現集群配置更新。

本文採用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

大家可以通過 分類 查看更多關於 Spring Cloud 的文章。

🤗 您的點贊轉發是對我最大的支持。

📢 掃碼關注 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕鬆噢 ~