目錄
- 前言
- 1. Nacos 配置中心基礎知識
- 1.1 Nacos 在配置中心中的功能
- 1.2 Nacos 配置管理 Data ID 的構成
- 1.3 Nacos 配置的復原機制
- 1.4 Nacos 配置的圖形化管理界面
- 1.5 Namespace、Group、Data ID 三者的關系
- 1.6 Nacos 對配置的 CRUD
- 1.7 Nacos 動态監聽的長輪詢機制
- 1.8 Nacos 配置中心的源碼分析
- 2. Nacos 基礎配置
- 2.1 下載下傳 Nacos 伺服器
- 2.2 引入 pom.xml 依賴檔案
- 2.3 修改 yml 配置檔案
- 2.4 在主程式類上添加注解
- 2.5 編寫業務類
- 2.6 在 Nacos 伺服器中添加配置資訊
- 2.7 報錯無法裝配 bean
- 3. Nacos 加載配置的三種方案
- 3.1 Data ID 方案
- 3.2 Group 方案
- 3.3 Namespace 方案
- 最後
參考資料:
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服務原理與實戰》
《B站 尚矽谷 SpringCloud 架構開發教程 周陽》
《Nacos 官網》
Nacos 緻力于解決微服務中的統一配置、服務注冊與發現等問題。它提供了一組簡單易用的特性集,幫助開發者快速實作動态服務發現、服務配置、服務中繼資料及流量管理;
- CRUD、版本管理、灰階管理、監聽管理、推送軌迹、聚合資料等功能;
-
;${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:即為目前環境對應的
。當 spring.profiles.active 為空時,對應的連接配接符 - 也将不存在,dataId 的拼接格式變成profile
${prefix}.${file-extension}
- file-exetension:為配置内容的資料格式,可以通過配置項
來配置。目前隻支援 properties 和 yaml 類型;spring.cloud.nacos.config.file-extension
- prefix:預設為
- Nacos 會記錄配置檔案的曆史版本預設保留 30 天,此外還有一鍵復原功能,復原操作将會觸發配置更新;
- 配置管理;
- 命名空間;
- 類似 Java 裡面的 package 名和類名,最外層的 Namespace 是可以用于區分部署環境的,Group 和 Data ID 邏輯上區分兩個目标對象;
- 預設情況下,
,Namespace=public
Group=DEFAULT_GROUP
Cluster=DEFAULT
- Namespace 命名空間:主要用來實作隔離,用于解決多環境及多租戶資料的隔離問題。比如有三個環境:開發、測試、生産環境,可以建立三個Namespace,不同的Namespace 之間是隔離的;
- Group 分組:可以把不同的微服務劃分到同一個分組裡面去,用來實作 Data ID 分組管理的機制;
- Data ID:通常用于組織劃分系統的配置集;
- Cluster 簇:對指定微服務的一個虛拟劃分;
- Instance 執行個體:微服務的執行個體;
- 官方的建議是,通過 Namespace 來區分不同的環境,而 Group 可以專注在業務層面的資料分組;
- 主要通過提供 Open API 接口或 SDK 實作;
- 用戶端通過 Open API 或調用 SDK 接口發送請求給伺服器,伺服器解析請求,并做相應的處理;
對配置的操作 | 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 | 訂閱感興趣的配置,當配置發生變化時可以收到一個事件 |
- 一般來說,動态監聽有兩種機制:
比較項 | Pull 機制 | Push 機制 |
---|---|---|
用戶端從服務端主動拉取資料 | 服務端主動把資料推送到用戶端 | |
缺點 | 不能保證資料實時性;在服務端配置長時間不更新的情況下,用戶端的定時任務會做一些無效的 Pull | 如果用戶端的數量比較多,服務端需要耗費大量的記憶體資源來儲存每個連接配接;需要心跳機制來維持每個連接配接狀态 |
- Nacos 的解決方案:長輪詢機制:
- 如果用戶端發起 Pull 請求,服務端收到請求之後,先檢查配置是否發生了變更:
- 變更:傳回變更配置;
- 無變更:設定一個定時任務,延期 29.5s 執行,把目前的用戶端長輪詢連接配接加入 allSubs 隊列;
- 在這 29.5s 内的配置變化:
- 配置無變化:等待 29.5s 後觸發自動檢查機制,傳回配置;
- 配置變化:在 29.5s 内任意一個時刻配置變化,會觸發一個事件機制,監聽到該事件的任務會周遊 allSubs 隊列,找到發生變更的配置項對應的 ClientLongPolling 任務,将變更的資料通過該任務中的連接配接進行傳回。相當于完成了一次 PUSH 操作;
- 長輪詢機制結合了 Pull 機制和 Push 機制的優點;
- 源碼分析詳情請見:微服務架構 | *2.5 Nacos 長輪詢定時機制的源碼分析;
- 由于篇幅有限,該内容放在以下兩篇文章:
- 點選跳轉:微服務架構 | *2.3 Spring Cloud 啟動及加載配置檔案源碼分析(以 Nacos 為例)
- 點選跳轉:微服務架構 | *2.4 Nacos 擷取配置與事件訂閱機制的源碼分析
- 點選跳轉:微服務架構 | *2.5 Nacos 長輪詢定時機制的源碼分析
以 Data ID 方案為例,更多方案詳情請見本篇第三點《3. Nacos 加載配置的三種方案》;
- 詳情請見:《微服務架構 | 3.2 Alibaba Nacos 注冊中心》的 2. 安裝并運作 Nacos 伺服器;
<!--nacos-config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 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 # 表示開發環境
- @EnableDiscoveryClient:使用其他元件(Nacos、zookeeper、Consul)作為注冊中心;
- 這裡僅編寫一個 controller 作為示例:
@RestController
@RefreshScope //使目前類下的配置支援 Nacos 的動态重新整理功能
public class ConfigClientController{
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
- 在 Nacos 伺服器裡建立并添加配置:
- 啟動服務,調用接口:
擷取配置資訊;http://localhost:18082/config/info
- 注意:如果
和 Nacos 伺服器配置的.yml
比對不上,将導緻 ConfigClientController 類裡的Data ID
找不到,最終報 ConfigClientController 無法裝配的錯誤,如下:${config.info}
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]
......
- 以下對 bootstrap.yml 的修改都可以在啟動時配置 JVM 環境替代,使用如下指令:
-
-Dspring.profiles.active=${profile}
- 建立三個 Data ID 的環境:
- 指定
中的配置,重新開機服務,可以看到配置已經切換成其他環境了:spring.profile.active
spring:
profiles:
active: prod
- 建立三個 Group 的環境:
-
和spring.profile.active
spring.cloud.nacos.config.group
spring:
profiles:
active: info #修改
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 #新增
- 建立兩個 Namespace 的環境:
- 克隆 / 建立幾份配置檔案到新的命名空間,然後編輯修改;
-
spring.profile.active
spring.cloud.nacos.config.group
spring:
profiles:
active: dev #修改
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,在建立命名空間時會給出
新人制作,如有錯誤,歡迎指出,感激不盡!
歡迎關注公衆号,會分享一些更日常的東西!
如需轉載,請标注出處!