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



前言

參考資料
《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,在新建命名空間時會給出

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



最后

新人制作,如有錯誤,歡迎指出,感激不盡!
歡迎關注公眾號,會分享一些更日常的東西!
如需轉載,請標注出處!


免責聲明!

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



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