Java微服務新生代Nacos之配置管理
- 2019 年 10 月 5 日
- 筆記
前言
在上文 Java 微服務新生代之 Nacos 已經介紹了微服務框架 Nacos 以及它在服務註冊與發現的功能,本文將主要介紹它的另一強大功能:配置管理,學習利用 Nacos 如何實現通過統一的管理介面,集中化實現分散式服務的配置維護和實時更新。
本文主要內容涉及如下:
- Nacos 配置管理概念介紹
- 如何 Nacos 管理配置
- Nacos 多環境配置管理
介紹 Nacos 配置管理
Nacos 提供了動態配置服務,能讓我們可以實時進行服務應用的配置變更,讓配置管理變得更加高效和快捷。它基於 key/value 方式存儲應用配置和其他元數據資訊,為分散式系統中的外部化配置提供伺服器端和客戶端支援。
首先了解下 Nacos 在配置管理模組上的幾個重要概念,能幫助我們更好的理解和正確的使用 Nacos 進行配置管理。
- 命名空間(Namespace) 用於進行租戶粒度的配置隔離,可用於對不同環境配置的區分隔離,例如開發測試環境和生產環境的資源(如配置、服務)隔離等。
- 配置項 (Configuration Item) 一個具體的可配置的參數與其值,通常以 param-key=param-value 的形式存在。例如我們常配置系統的日誌輸出級別(logLevel=INFO|WARN|ERROR) 就是一個配置項。
- 配置集 (Configuration Set) 一組相關或者不相關的配置項的集合。一個配置文件通常就是一個配置集,它可能包含了數據源、執行緒池、日誌級別等配置項。
- 配置集 ID(Data ID) 某個配置集的標識 ID,用於組織劃分系統的配置集。一個系統或者應用可以包含多個配置集。官方推薦採用類 Java 包(如 com.taobao.tc.refund.log.level)的命名規則定義 Data ID 來保證全局唯一性。
- 配置分組(Group) 對配置集進行分組,用於區分 Data ID 相同的配置集。默認採用 DEFAULT_GROUP 。配置分組的常見場景:不同的應用或組件使用了相同的配置類型,如 database_url 配置和 消息隊列 Topic 配置等。
啟動 Nacos 配置管理
要使用 Nacos 進行配置管理,首先需要啟動 Nacos 服務端,然後客戶端接入,關於 Nacos 的服務端啟動具體操作可以參見 Java 微服務新生代之 Nacos 。
啟動了 Nacos 服務端,首先我們在 Nacos 控制台上的配置管理里新建一個最簡單的配置,如圖:

image-20190623141751675
保存成功後能列表裡看下創建的配置記錄如下:

image-20190623141953948
每個配置集的操作欄都提供了配置的查看修改和清除功能,還有額外的示例程式碼查看,來引導我們如何在客戶端使用 Nacos 讀取該配置集,目前只支援 Java,Spring Boot,Spring Cloud,其他語言的版本還在完善語言。

image-20190623142049041接下里看下Nacos 基於 Spring 技術棧的集成方式
Nacos Spring
- 首先給 Spring 程式添加依賴 <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-spring-context</artifactId> <version>0.2.3-RC1</version> </dependency>
最新版本可以在 maven 倉庫 mvnrepository.com 中獲取。
- 添加
@EnableNacosConfig註解啟用 Nacos Spring 的配置管理服務。如下示例,我們使用了@NacosPropertySource註解載入了我們先前創建的配置集,並且指定為自動刷新配置。

- 通過 Nacos 的
@NacosValue註解將配置項與屬性進行綁定。

- 啟動程式後,打開
http://localhost:8080/config/hello獲取返回結果hello,test,內容如下就表示讀取配置成功。

- 讀取成功後我們再嘗試修改這個配置項驗證下 Nacos 的配置資訊的動態刷新特性。修改有兩種方式,一種在 Nacos 控制台上手動修改,另一種在命令行使用提供的 API 直接進行修改: curl -X POST "http://127.0.0.1:8848/nacos/v1.0.1/cs/configs?dataId=com.one.learn.nacos.config&group=DEFAULT_GROUP&content=message=nacos-spring"
- 再次訪問
http://localhost:8080/config/hello,此時返回內容為hello,nacos-spring,返回資訊變化說明程式中的message值已經被動態更新了。

Nacos Spring Boot
- 添加配置動態變更的依賴: <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version>0.2.1</version> </dependency>
注意:這裡的版本 0.2.x.RELEASE 對應的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 對應的是 Spring Boot 1.x 版本。
- 在
application.properties中配置 Nacos Server 的地址:nacos.config.server-addr=127.0.0.1:8848 - 使用
@NacosPropertySource載入dataId為com.one.learn.nacos.config的配置源,並開啟自動更新:

- 通過 Nacos 的
@NacosValue註解設置屬性值,與集成 Spring 的步驟內容一樣。 - 啟動引導類,打開
http://localhost:8080/config/hello獲取返回結果hello,nacos, 說明程式中的配置已經讀取成功。
Nacos Spring Cloud
如果使用 Spring Cloud 程式,Nacos 提供了依賴庫 spring-cloud-starter-alibaba-nacos-config 實現配置的動態變更。
- 添加依賴: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>0.9.0.RELEASE</version> </dependency>
注意:版本 0.2.x.RELEASE 對應的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 對應的是 Spring Boot 1.x 版本。
- 在
bootstrap.properties中配置 Nacos server 的地址和應用名如下,在 Nacos Spring Cloud 中,dataId默認為spring.application.name加上properties文件後綴,所以,為了能正確讀取配置,我們需要將 Nacos 上配置集 ID 為com.one.learn.nacos.config調整為com.one.learn.nacos.config.propertiesspring.cloud.nacos.config.server-addr=127.0.0.1:8848spring.application.name=com.one.learn.nacos.config這裡使用 bootstrap.properties 作為配置 Nacos 地方,是因為 Spring Boot 配置文件的載入順序,依次為 bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml ,在application層級上配置 Nacos 時無法生效。
注意:當使用域名的方式來訪問 Nacos 時,
spring.cloud.nacos.config.server-addr配置的方式必須為域名:port。即使使用域名,埠不能省略。例如 Nacos 的域名為 abc.com.nacos,監聽的埠為 80,則spring.cloud.nacos.config.server-addr=abc.com.nacos:80。
- 通過 Spring Cloud 原生註解
@RefreshScope實現配置自動更新:

- 運行程式,訪問
http://localhost:8080/config/hello,返回內容為hello,nacos,則表示配置讀取成功。 - 在 Nacos 控制台修改配置項
message=Nacos Spring Cloud,再次訪問http://localhost:8080/config/hello, 返回內容為hello,Nacos Spring Cloud,說明程式中的message值已經被動態更新了。
Nacos 多環境配置管理
上面實現了 Nacos 基本的配置讀取和更新後,接下來我們看下 Nacos 如何進行多環境配置的管理,需要注意的是此特性僅針對於 Spring Cloud 應用。
假設我們程式有兩個環境:測試,生產環境需要管理配置,在 Spring Boot 程式中,默認的配置文件為 application.properties,傳統的方式是,利用 Spring Profile 特性,在項目里存放多個環境對應的配置文件,文件格式為 application-${env}-properties,並且需要用 spring.profile.active 指定啟動時應用哪個環境的配置。
Nacos Config 主要通過 dataId 和 group 來唯一確定一條配置,在 Nacos Spring Cloud 中,dataId 的完整格式如下:
${prefix}-${spring.profile.active}.${file-extension} prefix默認為spring.application.name的值,也可以通過配置項spring.cloud.nacos.config.prefix來配置。spring.profile.active即為當前環境對應的 profile,詳情可以參考 Spring Boot 文檔。
注意:當 spring.profile.active 為空時,對應的連接符 - 也將不存在,dataId 的拼接格式變成 {prefix}.{file-extension}
file-exetension為配置內容的數據格式,可以通過配置項spring.cloud.nacos.config.file-extension來配置。目前只支援properties和yaml類型。
group 默認為 DEFAULT_GROUP,可以通過 spring.cloud.nacos.config.group 自定義指定名稱。
- 基於上面的配置規則描述,我們可以先在 Nacos 控制台上新建兩個不同環境的配置集,如下

image-20190623171248544都存放兩個配置項,以 property 文件格式存儲。
#nacos-config-prod.propertiesserver.port=8091message=nacos-config-prod#nacos-config-test.propertiesserver.port=8081message=nacos-config-test- 然後在程式的主配置文件
application.properties中配置如下:spring.cloud.nacos.config.server-addr=127.0.0.1:8848spring.application.name=nacos-configspring.cloud.nacos.config.file-extension=propertiesspring.profile.active=test - 編寫測試控制器類 ConfigController,將配置項與屬性值進行綁定。

- 啟動程式,可以看到如下數據結果,說明測試環境下埠配置已經生效。

再通過瀏覽器訪問 http://localhost:8081/config/hello,返回 hello,nacos-config-test 。
- 修改配置文件
application.properties的spring.profile.active,重新啟動程式並訪問http://localhost:8091/config/hellospring.cloud.nacos.config.server-addr=127.0.0.1:8848spring.application.name=nacos-configspring.cloud.nacos.config.file-extension=propertiesspring.profile.active=prod能獲取到返回結果hello,nacos-config-prod, 也說明程式另一個環境的配置切換成功。
配置監聽
除了主動檢驗配置生效之外,我們可以通過添加監聽器的方式來監聽配置的變化,實現很簡單,使用 @NacosConfigListener 即可,一旦指定的配置集 ID 對應配置發生了變化,監聽器就會受到回調,將所有的配置資訊以字元串形式返回。

當存在多個配置項時,回調接收到的配置字元串中帶有換行格式,需要自己處理。
當然 @NacosConfigListener 也支援類型轉換,比如轉換為 Properties 對象

Namespace 最佳實踐
Nacos 里 Namespace 作為租戶顆粒度細分而存在,主要為了解決多環境以及多租戶數據(配置和服務)隔離的問題。
- 如果只是一個租戶(用戶),不同的 namespce 可以對應不同的環境,以此實現環境配置的隔離,效果就跟上節內容:Nacos 多環境配置管理 相似。

img
- 如果存在多個租戶,為每個租戶分配不同的 namespace,這樣每個租戶(用戶)的配置數據以及註冊的服務數據都會歸屬到自己的 namespace 下,就可以實現多租戶配置數據隔離作用。

img
注意:Nacos 目前還沒實現帳號許可權的分配和隔離,無法讓各租戶自己管理自己的配置,這一塊功能仍在規劃中。
簡單介紹之後,再來看下 namespace 相關的最佳實踐:
- 如何來獲取 namespace 的值。
- namespace 參數初始化方式。
創建命名空間
在 nacos 的控制台左邊功能側看到有一個 命名空間 的功能,點擊就可以看到 新建命名空間 的按鈕,那麼這個時候就可以創建自己的命名空間了。創建成功之後,會生成一個命名空間 ID,主要是用來避免命名空間名稱有可能會出現重名的情況。因此當您在應用中需要配置指定的 namespace 時,填入的是命名空間 ID。

image-20190623180238812
關聯命令空間
在沒有明確指定 ${spring.cloud.nacos.config.namespace} 配置的情況下, 默認使用的是 Nacos 上 Public 這個 namespae。如果需要使用自定義的命名空間,可以通過以下配置來實現:
spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7
該配置必須放在 bootstrap.properties 文件中。此外
spring.cloud.nacos.config.namespace的值是 namespace 對應的 id。
結語
到這裡,到這裡關於 Nacos 管理配置的學習就告一段落,當然在配置管理上還有更多的用法,Nacos 官方文檔描述的也很詳細,大家也可以多在官網上查閱。後續我將繼續深入研究其他 Spring Cloud Alibaba 微服務生態的組件。
程式碼示例
示例項目:nacos-actions:https://github.com/wrcj12138aaa/nacos-actions 環境支援:
- JDK 8
- Maven 3.6.0
- SpringBoot 2.1.0.RELEASE
- SpringCloud Greenwich.RELEASE
- SpringCloudAlibaba 0.9.0.RELEASE
參考
- Java 微服務新生代之 Nacos:https://mp.weixin.qq.com/s/vS36glyNoD26GL6cbNs5Qw
- Nacos 概念: https://nacos.io/zh-cn/docs/concepts.html
- Spring Cloud Alibaba 基礎教程:Nacos 配置的多環境管理:http://blog.didispace.com/spring-cloud-alibaba-nacos-config-2/
- Nacos 官方文檔:https://nacos.io/zh-cn/docs/what-is-nacos.html