微服務架構 | 2.2 Alibaba Nacos 的統一配置管理

多氯環己烷發表於2022-01-21


前言

參考資料
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服務原理與實戰》
《B站 尚矽谷 SpringCloud 框架開發教程 周陽》
《Nacos 官網》

Nacos 致力於解決微服務中的統一配置、服務註冊與發現等問題。它提供了一組簡單易用的特性集,幫助開發者快速實現動態服務發現、服務配置、服務後設資料及流量管理;


1. Nacos 配置中心基礎知識

1.1 Nacos 在配置中心中的功能

  • CRUD、版本管理、灰度管理、監聽管理、推送軌跡、聚合資料等功能;

1.2 Nacos 配置管理 Data ID 的構成

  • ${prefix}-${spring.profiles.active}.${file-extension}
  • 預設為:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
    • prefix:預設為 spring.application.name 的值,也可以通過配置項 spring.cloud.nacos.config.prefix 來配置;
    • spring.profiles.active:即為當前環境對應的 profile。當 spring.profiles.active 為空時,對應的連線符 - 也將不存在,dataId 的拼接格式變成 ${prefix}.${file-extension}
    • file-exetension:為配置內容的資料格式,可以通過配置項 spring.cloud.nacos.config.file-extension 來配置。目前只支援 properties 和 yaml 型別;

Nacos 配置管理 dataId 的構成

1.3 Nacos 配置的回滾機制

  • Nacos 會記錄配置檔案的歷史版本預設保留 30 天,此外還有一鍵回滾功能,回滾操作將會觸發配置更新;

Nacos 配置的回滾

1.4 Nacos 配置的圖形化管理介面

  • 配置管理;

配置列表

  • 名稱空間;

名稱空間

1.5 Namespace、Group、Data ID 三者的關係

Namespace、Group、Data ID 三者的關係

  • 類似 Java 裡面的 package 名和類名,最外層的 Namespace 是可以用於區分部署環境的,GroupData ID 邏輯上區分兩個目標物件;

  • 預設情況下,Namespace=publicGroup=DEFAULT_GROUPCluster=DEFAULT

    • Namespace 名稱空間:主要用來實現隔離,用於解決多環境及多租戶資料的隔離問題。比如有三個環境:開發、測試、生產環境,可以建立三個Namespace,不同的Namespace 之間是隔離的;
    • Group 分組:可以把不同的微服務劃分到同一個分組裡面去,用來實現 Data ID 分組管理的機制;
    • Data ID:通常用於組織劃分系統的配置集;
    • Cluster 簇:對指定微服務的一個虛擬劃分;
    • Instance 例項:微服務的例項;
  • 官方的建議是,通過 Namespace 來區分不同的環境,而 Group 可以專注在業務層面的資料分組;

1.6 Nacos 對配置的 CRUD

  • 主要通過提供 Open API 介面或 SDK 實現;
  • 客戶端通過 Open API 或呼叫 SDK 介面傳送請求給伺服器,伺服器解析請求,並做相應的處理;

配置的 CRUD

對配置的操作 SDK Open API 說明
釋出配置 public boolean publishConfig(String dataId, String group, String content) throws NacosException POST: /nacos/v1/cs/configs 將配置儲存到 Nacos Config Server 中
刪除配置 public boolean removeConfig(String dataId, String group)throws NacosException DELETE: /nacos/v1/cs/configs 刪除配置中心的指定配置
獲取配置 public string getConfig(String dataId, String group, long timeoutMs) throws NacosException GET: /nacos/v1/cs/configs 從 Nacos Config Server 中讀取配置
監聽配置 public void addListener(String dataId, String group, Listener listener) POST: /nacos/v1/cs/configs/listener 訂閱感興趣的配置,當配置發生變化時可以收到一個事件

1.7 Nacos 動態監聽的長輪詢機制

  • 一般來說,動態監聽有兩種機制:
比較項 Pull 機制 Push 機制
說明 客戶端從服務端主動拉取資料 服務端主動把資料推送到客戶端
缺點 不能保證資料實時性;在服務端配置長時間不更新的情況下,客戶端的定時任務會做一些無效的 Pull 如果客戶端的數量比較多,服務端需要耗費大量的記憶體資源來儲存每個連線;需要心跳機制來維持每個連線狀態
  • Nacos 的解決方案:長輪詢機制

Nacos 動態監聽的長輪詢機制

  • 如果客戶端發起 Pull 請求,服務端收到請求之後,先檢查配置是否發生了變更:
    • 變更:返回變更配置;
    • 無變更:設定一個定時任務,延期 29.5s 執行,把當前的客戶端長輪詢連線加入 allSubs 佇列;
  • 在這 29.5s 內的配置變化:
    • 配置無變化:等待 29.5s 後觸發自動檢查機制,返回配置;
    • 配置變化:在 29.5s 內任意一個時刻配置變化,會觸發一個事件機制,監聽到該事件的任務會遍歷 allSubs 佇列,找到發生變更的配置項對應的 ClientLongPolling 任務,將變更的資料通過該任務中的連線進行返回。相當於完成了一次 PUSH 操作;
  • 長輪詢機制結合了 Pull 機制和 Push 機制的優點;
  • 原始碼分析詳情請見:微服務架構 | *2.5 Nacos 長輪詢定時機制的原始碼分析

1.8 Nacos 配置中心的原始碼分析


2. Nacos 基礎配置

以 Data ID 方案為例,更多方案詳情請見本篇第三點《3. Nacos 載入配置的三種方案》;

2.1 下載 Nacos 伺服器

2.2 引入 pom.xml 依賴檔案

<!--nacos-config-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2.3 修改 yml 配置檔案

  • bootstrap.yml
# nacos配置
server:
  port: 18082

spring:
  application:
    name: nacos-config-client     #必須,構成 Nacos 配置管理 Data ID 欄位的一部分
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848     #Nacos 服務註冊中心地址
      config:
        server-addr: localhost:8848     #Nacos 作為配置中心地址
        file-extension: yaml     #指定 yaml 格式的配置
        
        # prefix: hhh     #Data ID 的字首,如果不指定,就是 nacos-config-client-dev.yaml。指定後,是 hhh-dev.yaml
        # refresh: true      #是否動態重新整理
        
        # group: DEFAULT_GROUP     #指定組
        # namespace: PUBLIC     #指定名稱空間 ID
  • application.yml
spring:
  profiles:
    active: dev # 表示開發環境

2.4 在主程式類上新增註解

  • @EnableDiscoveryClient:使用其他元件(Nacos、zookeeper、Consul)作為註冊中心;

2.5 編寫業務類

  • 這裡僅編寫一個 controller 作為示例:
@RestController
@RefreshScope //使當前類下的配置支援 Nacos 的動態重新整理功能
public class ConfigClientController{
    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }
}

2.6 在 Nacos 伺服器中新增配置資訊

  • 在 Nacos 伺服器裡新建並新增配置:

Nacos 新建配置
Nacos 新建配置2
Nacos 新建配置成功

  • 啟動服務,呼叫介面:http://localhost:18082/config/info 獲取配置資訊;

啟動服務,呼叫介面

2.7 報錯無法裝配 bean

  • 注意:如果 .yml 和 Nacos 伺服器配置的 Data ID 匹配不上,將導致 ConfigClientController 類裡的 ${config.info} 找不到,最終報 ConfigClientController 無法裝配的錯誤,如下:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.configClientController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'config.info' in value "${config.info}"
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:380) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$1(AbstractBeanFactory.java:356) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.cloud.context.scope.GenericScope$BeanLifecycleWrapper.getBean(GenericScope.java:389) ~[spring-cloud-context-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.cloud.context.scope.GenericScope.get(GenericScope.java:186) ~[spring-cloud-context-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.springframework.cloud.context.scope.refresh.RefreshScope.eagerlyInitialize(RefreshScope.java:134) ~[spring-cloud-context-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.cloud.context.scope.refresh.RefreshScope.start(RefreshScope.java:125) ~[spring-cloud-context-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.cloud.context.scope.refresh.RefreshScope.onApplicationEvent(RefreshScope.java:119) ~[spring-cloud-context-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.cloud.context.scope.refresh.RefreshScope.onApplicationEvent(RefreshScope.java:73) ~[spring-cloud-context-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	......

3. Nacos 載入配置的三種方案

  • 以下對 bootstrap.yml 的修改都可以在啟動時配置 JVM 環境替代,使用如下命令:
  • -Dspring.profiles.active=${profile}

3.1 Data ID 方案

  • 新建三個 Data ID 的環境:

三個 Data ID 的環境

  • 指定 spring.profile.active 中的配置,重啟服務,可以看到配置已經切換成其他環境了:
spring:
  profiles:
    active: prod

配置切換成其他環境

3.2 Group 方案

  • 新建三個 Group 的環境:

三個 Group 的環境

  • 指定 spring.profile.activespring.cloud.nacos.config.group 中的配置,重啟服務,可以看到配置已經切換成其他環境了:
  • application.yml
spring:
  profiles:
    active: info #修改
  • bootstrap.yml
server:
  port: 18082
spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 
      config:
        server-addr: localhost:8848
        file-extension: yaml
        group: PROD_GROUP #新增

配置切換成其他 Group 環境

3.3 Namespace 方案

  • 新建兩個 Namespace 的環境:

新建兩個名稱空間
三個名稱空間

  • 克隆 / 新建幾份配置檔案到新的名稱空間,然後編輯修改;

克隆三份配置檔案到其他名稱空間

  • 指定 spring.profile.activespring.cloud.nacos.config.group 中的配置,重啟服務,可以看到配置已經切換成其他環境了:
  • application.yml
spring:
  profiles:
    active: dev #修改
  • bootstrap.yml
server:
  port: 18082
spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 
      config:
        server-addr: localhost:8848
        file-extension: yaml
        group: DEFAULT_GROUP #新增
        namespace: 48b2da7d-0b26-4c15-907b-9a379db8f7de #新增,名稱空間的 ID,在新建名稱空間時會給出

配置切換成其他名稱空間環境



最後

新人制作,如有錯誤,歡迎指出,感激不盡!
歡迎關注公眾號,會分享一些更日常的東西!
如需轉載,請標註出處!
微服務架構 | 2.2 Alibaba Nacos 的統一配置管理

相關文章