1. 簡介
Nacos 提供用於存儲配置和其他元數據的 key/value 存儲,為分佈式系統中的外部化配置提供服務器端和客戶端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 應用的外部屬性配置。
Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案,客戶端和服務器上的概念與 Spring Environment 和 PropertySource 有著一致的抽象,在特殊的 bootstrap 階段,配置被加載到 Spring 環境中。當應用程序通過部署管道從開發到測試再到生產時,您可以管理這些環境之間的配置,並確保應用程序具有遷移時需要運行的所有內容。Nacos 的獲取和啟動方式可以參考 Nacos 官網。
注:如果讀者是阿里雲商業化組件 ANS 或 ACM 用戶,請使用 Nacos Config 代替對應的組件。
2. 學習目標
- 使用 Nacos Config 作為 Spring Cloud 分佈式配置
- 使用 Nacos Config 實現 Bean 動態刷新
- 瞭解 Nacos Config 高級配置
3. 詳細內容
- 快速上手:使用 Nacos Config 作為外部化配置源
- 多文件擴展名支持:以 YAML 文件擴展名為例,討論 Nacos Config 多文件擴展名支持
- 動態配置更新:演示 @RefreshScope 特性,實現 Bean 動態刷新
- 自定義擴展:自定義 namespace、Group 以及 Data Id 的配置擴展
- 運維特性:演示 Nacos Config 高級外部化配置以及 Endpoint 內部細節
4. 快速上手
4.1 如何引入 Nacos Config 支持分佈式配置
Nacos Config 引入的方式同樣也有兩種,即 Aliyun Java Initializr 引入和 Maven pom.xml 依賴。官方推薦使用 Aliyun Java Initializr 方式引入 Nacos Discovery,以便簡化組件之間的依賴關係。
4.1.1 [簡單] 通過 Aliyun Java Initializr 創建工程並引入 Nacos Config(推薦)
由於 Spring Cloud 組件的版本和依賴較為複雜,推薦讀者使用 Aliyun Java Initializr 構建應用工程。
讀者選擇偏好的 Web 瀏覽器訪問 Aliyun Java Initializr,其資源網址為:https://start.aliyun.com/bootstrap.html
下文以 Google Chrome 瀏覽器為例,當網頁加載後,首先,在 "項目基本信息" 部分輸入 Group :“com.alibaba.cloud” 以及 Artifact:“nacos-config-sample”。然後,“組件依賴” 輸入框搜索:“Nacos Config”,選擇 "Nacos Configuration",如下所示:
同上組件操作,增加 “Spring Web” 和 “Spring Boot Actuator” 組件:
組件選擇後,點擊 “生成” 高亮按鈕。隨後,平臺將生成一個名為 “nacos-config-sample.zip” 的壓縮文件,將其保存到本地目錄,並解壓該文件,工程目錄將隨之生成。打開目錄下的 pom.xml 文件,不難發現 Nacos starter 聲明其中(以下 XML 內容均來自於項目根路徑中的 pom.xml 文件):
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
不過該 starter 並未指定版本,具體的版本聲明在 com.alibaba.cloud:spring-cloud-alibaba-dependencies 部分:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
其中,${spring-cloud-alibaba.version} 和 ${spring-boot.version} 分別為 Spring Cloud Alibaba 和 Spring Boot 組件依賴的版本,它們的版本定義在 <properties>
元素中,即 2.2.1.RELEASE 和 2.3.0.RELEASE:
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>
如果讀者非常熟悉 Maven 依賴管理的配置方式,可以考慮 Maven pom.xml 依賴 Nacos Config。
4.1.2 [高級] 通過 Maven pom.xml 依賴 Nacos Config
如果要在您的項目中使用 Nacos 來實現服務註冊/發現,使用 group ID 為 com.alibaba.cloud
和 artifact ID 為 spring-cloud-starter-alibaba-nacos-config
的 starter。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
該聲明方式同樣需要聲明 com.alibaba.cloud:spring-cloud-alibaba-dependencies,內容與上小節相同,在此不再贅述。下一節將討論如何使用 Nacos Config 支持分佈式配置。
4.1.3 [偷懶] 直接在沙箱裡查看應用代碼
點擊 鏈接,直接訪問沙箱環境,這裡會有為你準備好的案例代碼^_^。
4.2 使用 Nacos Config 實現分佈式配置
使用 Nacos Config 實現分佈式配置與 Spring Cloud Consul 和 Spring Cloud Zookeeper 的方式非常類似,僅需添加相關外部化配置即可工作。換言之,Nacos Config 同樣不會侵入應用代碼,方便應用整合和遷移,如果讀者熟悉 Spring Cloud Consul 或 Spring Cloud Zookeeper 使用方式 的話,通常需要將 Consul 或 Zookeeper 服務進程預先部署,Nacos Config 也如此。
4.2.1 啟動 Nacos 服務器
我們為開發者提供了一套免費的 Nacos Server :進入 http://139.196.203.133:8848/nacos/ 查看控制檯(賬號名/密碼為 nacos-configuration/nacos-configuration),選擇 "配置管理/配置列表":
由於服務是公共免費的,為了做好隔離,所以分佈式配置的功能,請選擇在 sandbox-configuration 的命名空間下操作。
具體啟動方式參考 Nacos 官網。
關於更多的 Nacos Server 版本,可以從 release 頁面 下載最新的版本。
4.2.2 添加 Nacos 配置
點擊“配置列表”頁面右側的 "+" 號(紅色箭頭所指):
瀏覽器跳轉新頁面,並填充內容如下:
其中,Data ID 由應用名(nacos-config-sample)+ 文件後綴名(.properties) 組成,點擊“發佈”按鈕(紅色箭頭所指),配置內容為:
user.name=nacos-config-sample
user.age=90
發佈成功後,控制檯會出現提示彈出框。
特別提醒
圖片中的 Data ID 中的應用名,使用的是 nacos-config-sample 。如果使用我們提供的 Nacos Server ,由於多個用戶同時使用,可能存在應用名衝突的問題。建議修改為跟別人都不重複的應用名:
spring.application.name=xxxxxx
替換上面的xxxxx部分
4.2.3 配置應用 Nacos Config Server 地址
回到應用 nacos-config-sample 工程,在 resources 目錄下新建名為 “application.properties" 文件,並配置以下內容:
spring.cloud.nacos.config.server-addr=139.196.203.133:8848
spring.cloud.nacos.config.username=nacos-configuration
spring.cloud.nacos.config.password=nacos-configuration
spring.cloud.nacos.config.namespace=sandbox-configuration
注意,Nacos Server 地址必須配置在 application.properties 文件。
注意當你使用域名的方式來訪問 Nacos 時,
spring.cloud.nacos.config.server-addr
配置的方式為域名:port。 例如 Nacos 的域名為abc.com.nacos,監聽的端口為 80,則spring.cloud.nacos.config.server-addr=abc.com.nacos:80
。 注意 80 端口不能省略。
4.2.4 添加讀取 Nacos Config 實現
修改 nacos-config-sample 引導類,如下所示:
@SpringBootApplication
public class NacosConfigSampleApplication {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@PostConstruct
public void init() {
System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
}
public static void main(String[] args) {
SpringApplication.run(NacosConfigSampleApplication.class, args);
}
}
4.2.5 啟動 Nacos Config 應用
運行 nacos-config-sample 引導類 NacosConfigSampleApplication
,觀察控制檯結果(截取關鍵日誌信息):
[init] user name : nacos-config-sample , age : 90
如果在沙箱內啟動應用,由於暫時還無法看到運行時的日誌,可以通過WEB 控制器的方式查看參數,具體操作見 5.1 節。
5. 使用 Nacos Config 實現 Bean 動態刷新
Nacos Confg 支持標準 Spring Cloud @RefreshScope
特性,即應用訂閱某個 Nacos 配置後,當配置內容變化時,Refresh Scope Beans 中的綁定配置的屬性將有條件的更新。所謂的條件是指 Bean 必須:
- 必須條件:Bean 的聲明類必須標註
@RefreshScope
-
二選一條件:
- 屬性(非 static 字段)標註
@Value
-
@ConfigurationProperties
Bean
- 屬性(非 static 字段)標註
除此之外,Nacos Confg 也引入了 Nacos Client 底層數據變化監聽接口,即 com.alibaba.nacos.api.config.listener.Listener
。下面的內容將分別討論這三種不同的使用場景。
Nacos Client:Nacos 客戶端 API,也是 Nacos Config 底層依賴
5.1 使用 Nacos Config 實現 Bean @Value
屬性動態刷新
基於應用 nacos-config-sample 修改,將引導類 NacosConfigSampleApplication
標註@RefreshScope
和 @RestController
,使得該類變為 Spring MVC REST 控制器,同時具備動態刷新能力,具體代碼如下:
@SpringBootApplication
@RestController
@RefreshScope
public class NacosConfigSampleApplication {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@PostConstruct
public void init() {
System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
}
@RequestMapping("/user")
public String user() {
return String.format("[HTTP] user name : %s , age : %d", userName, userAge);
}
public static void main(String[] args) {
SpringApplication.run(NacosConfigSampleApplication.class, args);
}
}
重啟引導類 NacosConfigSampleApplication
,控制檯輸出如故:
[init] user name : nacos-config-sample , age : 90
再通過命令行訪問 REST 資源 /user
:
% curl http://127.0.0.1:8080/user
[HTTP] user name : nacos-config-sample , age : 90
如果使用沙箱環境,請直接點擊應用列表
的訪問
按鈕,並在打開的瀏覽器窗口的地址欄中追加/user
,如下圖:
本文中,其他的基於 http 訪問的步驟類似,後面不在贅述。
本次請求結果中的 user name 和 age 數據與應用啟動時的一致,因為此時 Nacos Server 中的配置數據沒變化。
隨後,通過 Nacos 控制檯調整 nacos-config-sample.properties 配置,將 user.age 從 90 變更為 99:
點擊“發佈”按鈕,觀察應用日誌變化(部分內容被省略):
c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848] [data-received] dataId=nacos-config-sample.properties, group=DEFAULT_GROUP, tenant=null, md5=4a8cb29154adb9a0e897e071e1ec8d3c, content=user.name=nacos-config-sample
user.age=99, type=properties
o.s.boot.SpringApplication : Started application in 0.208 seconds (JVM running for 290.765)
o.s.c.e.event.RefreshEventListener : Refresh keys changed: [user.age]
- 第 1 和 2 行代碼是由 Nacos Client 輸出,通知開發者具體的內容變化,不難發現,這裡沒有輸出完整的配置內容,僅為變更部分,即配置 user.age。
- 第 3 行日誌似乎讓 SpringApplication 重啟了,不過消耗時間較短,這裡暫不解釋,後文將會具體討論,只要知道這與 Bootstrap 應用上下文相關即可。
- 最後一行日誌是由 Spring Cloud 框架輸出,提示開發人員具體變更的 Spring 配置 Property,可能會有多個,不過本例僅修改一處,所以顯示單個。
接下來,重新訪問 REST 資源 /user
:
% curl http://127.0.0.1:8080/user
[HTTP] user name : nacos-config-sample , age : 99
終端日誌顯示了這次配置變更同步到了 @Value("${user.age}") 屬性 userAge 的內容。除此之外,應用控制檯也輸出了以下內容:
[init] user name : nacos-config-sample , age : 99
而該日誌是由 init()
方法輸出,那麼是否說明該方法被框架調用了呢?答案是肯定的。既然 @PostConstruct
方法執行了,那麼 @PreDestroy
方法會不會被調用呢?不妨增加 Spring Bean 銷燬回調方法:
@SpringBootApplication
@RestController
@RefreshScope
public class NacosConfigSampleApplication {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@PostConstruct
public void init() {
System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
}
@PreDestroy
public void destroy() {
System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
}
...
}
再次重啟引導類 NacosConfigSampleApplication
,初始化日誌仍舊輸出:
[init] user name : nacos-config-sample , age : 99
將配置 user.age 內容從 99 調整為 18,觀察控制檯日誌變化:
c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848] [data-received] dataId=nacos-config-sample.properties, group=DEFAULT_GROUP, tenant=null, md5=e25e486af432c403a16d5fc8a5aa4ab2, content=user.name=nacos-config-sample
user.age=18, type=properties
o.s.boot.SpringApplication : Started application in 0.208 seconds (JVM running for 144.467)
[destroy] user name : nacos-config-sample , age : 99
o.s.c.e.event.RefreshEventListener : Refresh keys changed: [user.age]
相較於前一個版本,日誌插入了 destroy()
方法輸出內容,並且Bean 屬性 userAge 仍舊是變更前的數據 99。隨後,再次訪問 REST 資源 /user
,其中終端日誌:
% curl http://127.0.0.1:8080/user
[HTTP] user name : nacos-config-sample , age : 18
應用控制檯日誌:
[init] user name : nacos-config-sample , age : 18
兩者與前一版本並無差異,不過新版本給出了一個現象,即當 Nacos Config 接收到服務端配置變更時,對應的 @RefreshScope
Bean 生命週期回調方法會被調用,並且是先銷燬,然後由重新初始化。本例如此設計,無非想提醒讀者,要意識到 Nacos Config 配置變更對 @RefreshScope
Bean 生命週期回調方法的影響,避免出現重複初始化等操作。
注: Nacos Config 配置變更調用了 Spring Cloud API
ContextRefresher
,該 API 會執行以上行為。同理,執行 Spring Cloud Acutator Endpointrefresh
也會使用ContextRefresher
。
通過上述討論,相信讀者已對 Nacos 配置變更操作相當的熟悉,後文將不再贅述相關配置。接下來繼續討論 @ConfigurationProperties
Bean 的場景。
5.2 使用 Nacos Config 實現
@ConfigurationProperties
Bean 屬性動態刷新
在應用 nacos-config-sample 新增 User
類,並標註 @RefreshScope
和 @ConfigurationProperties
,代碼如下:
@RefreshScope
@ConfigurationProperties(prefix = "user")
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
根據 @ConfigurationProperties
的定義, User
類的屬性綁定到了配置屬性前綴 user
。下一步,調整引導類,代碼如下:
@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class NacosConfigSampleApplication {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@Autowired
private User user;
@PostConstruct
public void init() {
System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
}
@PreDestroy
public void destroy() {
System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
}
@RequestMapping("/user")
public String user() {
return "[HTTP] " + user;
}
public static void main(String[] args) {
SpringApplication.run(NacosConfigSampleApplication.class, args);
}
}
較前一個版本 NacosConfigSampleApplication
實現,主要改動點:
- 激活
@ConfigurationProperties
Bean@EnableConfigurationProperties(User.class)
- 通過
@Autowired
依賴注入User
Bean - 使用 user Bean( toString() 方法替換
user()
中的實現
下一步,重啟應用後,再將 user.age 配置從 18 調整為 99,控制檯日誌輸出符合期望:
[init] user name : nacos-config-sample , age : 18
......
[fixed-127.0.0.1_8848] [data-received] dataId=nacos-config-sample.properties, group=DEFAULT_GROUP, tenant=null, md5=b0f42fac52934faf69757c2b6770d39c, content=user.name=nacos-config-sample
user.age=90, type=properties
......
[destroy] user name : nacos-config-sample , age : 18
o.s.c.e.event.RefreshEventListener : Refresh keys changed: [user.age]
接下來,訪問 REST 資源 /user
,觀察終端日誌輸出:
% curl http://127.0.0.1:8080/user
[HTTP] User{name='nacos-config-sample', age=90}
User Bean 屬性成功地變更為 90,達到實戰效果。上小節提到 Nacos Config 配置變更會影響 @RefreshScope
Bean 的生命週期方法回調。同理,如果為 User
增加初始化和銷燬方法的話,也會出現行文,不過本次將 User
實現 Spring 標準的生命週期接口 InitializingBean
和 DisposableBean
:
@RefreshScope
@ConfigurationProperties(prefix = "user")
public class User implements InitializingBean, DisposableBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[afterPropertiesSet()] " + toString());
}
@Override
public void destroy() throws Exception {
System.out.println("[destroy()] " + toString());
}
}
代碼調整後,重啟應用,並修改配置(90 -> 19),觀察控制檯日誌輸出:
[init] user name : nacos-config-sample , age : 90
......
c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848] [data-received] dataId=nacos-config-sample.properties, group=DEFAULT_GROUP, tenant=null, md5=30d26411b8c1ffc1d16b3f9186db498a, content=user.name=nacos-config-sample
user.age=19, type=properties
......
[destroy()] User{name='nacos-config-sample', age=90}
[afterPropertiesSet()] User{name='nacos-config-sample', age=19}
[destroy] user name : nacos-config-sample , age : 90
......
o.s.c.e.event.RefreshEventListener : Refresh keys changed: [user.age]
不難發現, User
Bean 的生命週期方法不僅被調用,並且仍舊是先銷燬,再初始化。那麼,這個現象和之前看到的 SpringApplication
重啟是否有關係呢?答案也是肯定的,不過還是後文再討論。
下一小節將繼續討論怎麼利用底層 Nacos 配置監聽實現 Bean 屬性動態刷新
5.3 使用 Nacos Config 監聽實現 Bean 屬性動態刷新
前文曾提及 com.alibaba.nacos.api.config.listener.Listener
是 Nacos Client API 標準的配置監聽器接口,由於僅監聽配置內容,並不能直接與 Spring 體系打通,因此,需要藉助於 Spring Cloud Alibaba Nacos Config API NacosConfigManager
(感謝小夥伴 liaochuntao 和 zkzlx 的代碼貢獻),代碼調整如下:
@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class NacosConfigSampleApplication {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@Autowired
private User user;
@Autowired
private NacosConfigManager nacosConfigManager;
@Bean
public ApplicationRunner runner() {
return args -> {
String dataId = "nacos-config-sample.properties";
String group = "DEFAULT_GROUP";
nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("[Listener] " + configInfo);
}
});
};
}
@PostConstruct
public void init() {
System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
}
@PreDestroy
public void destroy() {
System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
}
@RequestMapping("/user")
public String user() {
return "[HTTP] " + user;
}
public static void main(String[] args) {
SpringApplication.run(NacosConfigSampleApplication.class, args);
}
}
代碼主要變化:
-
@Autowired
依賴注入NacosConfigManager
- 新增
runner()
方法,通過NacosConfigManager
Bean 獲取ConfigService
,並增加了AbstractListener
(Listener
抽象類)實現,監聽 dataId = "nacos-config-sample.properties" 和 group = "DEFAULT_GROUP" 的配置內容
重啟應用,並將配置 user.age 從 19 調整到 90,觀察日誌變化:
c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848] [data-received] dataId=nacos-config-sample.properties, group=DEFAULT_GROUP, tenant=null, md5=b0f42fac52934faf69757c2b6770d39c, content=user.name=nacos-config-sample
user.age=90, type=properties
[Listener] user.name=nacos-config-sample
user.age=90
......
在第 1 行日誌下方,新增了監聽實現代碼的輸出內容,不過這段內容是完整的配置,而非變化的內容。讀者請務必注意其中的差異。下一步要解決的是將配置映射到 Bean 屬性,此處給出一個簡單的解決方案,實現步驟有兩個:
- 將 String 內容轉化為 Properties 對象
- 將 Properties 屬性值設置到對應的 Bean 屬性
代碼調整如下:
@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class NacosConfigSampleApplication {
......
@Bean
public ApplicationRunner runner() {
return args -> {
String dataId = "nacos-config-sample.properties";
String group = "DEFAULT_GROUP";
nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("[Listener] " + configInfo);
System.out.println("[Before User] " + user);
Properties properties = new Properties();
try {
properties.load(new StringReader(configInfo));
String name = properties.getProperty("user.name");
int age = Integer.valueOf(properties.getProperty("user.age"));
user.setName(name);
user.setAge(age);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("[After User] " + user);
}
});
};
}
......
}
重啟應用,並將配置 user.age 從 90 調整到 19,觀察日誌變化:
[Listener] user.name=nacos-config-sample
user.age= 19
[Before User] User{name='nacos-config-sample', age=90}
[After User] User{name='nacos-config-sample', age=19}
上述三個例子均圍繞著 Nacos Config 實現 Bean 屬性動態更新,不過它們是 Spring Cloud 使用場景。如果讀者的應用僅使用 Spring 或者 Spring Boot,可以考慮 Nacos Spring 工程, Github 地址:https://github.com/nacos-group/nacos-spring-project,其中 @NacosValue
支持屬性粒度的更新。
6. Nacos Config 高級配置
6.1 支持自定義 namespace 的配置
首先看一下 Nacos 的 Namespace 的概念, Nacos 概念
用於進行租戶粒度的配置隔離。不同的命名空間下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用場景之一是不同環境的配置的區分隔離,例如開發測試環境和生產環境的資源(如配置、服務)隔離等。
在沒有明確指定 ${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,id 值可以在 Nacos 的控制檯獲取。並且在添加配置時注意不要選擇其他的 namespae,否則將會導致讀取不到正確的配置
6.2 支持自定義 Group 的配置
在沒有明確指定 ${spring.cloud.nacos.config.group}
配置的情況下, 默認使用的是 DEFAULT_GROUP 。如果需要自定義自己的 Group,可以通過以下配置來實現:
spring.cloud.nacos.config.group=DEVELOP_GROUP
注:該配置必須放在 bootstrap.properties 文件中。並且在添加配置時 Group 的值一定要和
spring.cloud.nacos.config.group
的配置值一致。
6.3 支持自定義擴展的 Data Id 配置
Spring Cloud Alibaba Nacos Config 從 0.2.1 版本後,可支持自定義 Data Id 的配置。關於這部分詳細的設計可參考 這裡。 一個完整的配置案例如下所示:
spring.application.name=opensource-service-provider
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# config external configuration
# 1、Data Id 在默認的組 DEFAULT_GROUP,不支持配置的動態刷新
spring.cloud.nacos.config.extension-configs[0].data-id=ext-config-common01.properties
# 2、Data Id 不在默認的組,不支持動態刷新
spring.cloud.nacos.config.extension-configs[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.extension-configs[1].group=GLOBALE_GROUP
# 3、Data Id 既不在默認的組,也支持動態刷新
spring.cloud.nacos.config.extension-configs[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.extension-configs[2].group=REFRESH_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true
可以看到:
- 通過
spring.cloud.nacos.config.extension-configs[n].data-id
的配置方式來支持多個 Data Id 的配置。 - 通過
spring.cloud.nacos.config.extension-configs[n].group
的配置方式自定義 Data Id 所在的組,不明確配置的話,默認是 DEFAULT_GROUP。 - 通過
spring.cloud.nacos.config.extension-configs[n].refresh
的配置方式來控制該 Data Id 在配置變更時,是否支持應用中可動態刷新, 感知到最新的配置值。默認是不支持的。
注:多個 Data Id 同時配置時,他的優先級關係是
spring.cloud.nacos.config.extension-configs[n].data-id
其中 n 的值越大,優先級越高。spring.cloud.nacos.config.extension-configs[n].data-id
的值必須帶文件擴展名,文件擴展名既可支持 properties,又可以支持 yaml/yml。 此時spring.cloud.nacos.config.file-extension
的配置對自定義擴展配置的 Data Id 文件擴展名沒有影響。
通過自定義擴展的 Data Id 配置,既可以解決多個應用間配置共享的問題,又可以支持一個應用有多個配置文件。
為了更加清晰的在多個應用間配置共享的 Data Id ,你可以通過以下的方式來配置:
# 配置支持共享的 Data Id
spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml
# 配置 Data Id 所在分組,缺省默認 DEFAULT_GROUP
spring.cloud.nacos.config.shared-configs[0].group=GROUP_APP1
# 配置Data Id 在配置變更時,是否動態刷新,缺省默認 false
spring.cloud.nacos.config.shared-configs[0].refresh=true
可以看到:
- 通過
spring.cloud.nacos.config.shared-configs[n].data-id
來支持多個共享 Data Id 的配置。 - 通過
spring.cloud.nacos.config.shared-configs[n].group
來配置自定義 Data Id 所在的組,不明確配置的話,默認是 DEFAULT_GROUP。 - 通過
spring.cloud.nacos.config.shared-configs[n].refresh
來控制該Data Id在配置變更時,是否支持應用中動態刷新,默認false。
6.4 配置的優先級
Spring Cloud Alibaba Nacos Config 目前提供了三種配置能力從 Nacos 拉取相關的配置。
- A: 通過
spring.cloud.nacos.config.shared-configs[n].data-id
支持多個共享 Data Id 的配置 - B: 通過
spring.cloud.nacos.config.extension-configs[n].data-id
的方式支持多個擴展 Data Id 的配置 - C: 通過內部相關規則(應用名、應用名+ Profile )自動生成相關的 Data Id 配置
當三種方式共同使用時,他們的一個優先級關係是:A < B < C
6.5 完全關閉配置
通過設置 spring.cloud.nacos.config.enabled = false 來完全關閉 Spring Cloud Nacos Config
6.6 更多高級配置
更多關於 Nacos Config Starter 的配置項如下所示:
配置項 | Key | 默認值 | 說明 |
---|---|---|---|
服務端地址 | spring.cloud.nacos.config.server-addr |
Nacos Server 啟動監聽的ip地址和端口 | |
配置對應的 DataId | spring.cloud.nacos.config.name |
先取 prefix,再取 name,最後取 spring.application.name | |
配置對應的 DataId | spring.cloud.nacos.config.prefix |
先取 prefix,再取 name,最後取 spring.application.name | |
配置內容編碼 | spring.cloud.nacos.config.encode |
讀取的配置內容對應的編碼 | |
GROUP | spring.cloud.nacos.config.group |
DEFAULT_GROUP |
配置對應的組 |
文件擴展名 | spring.cloud.nacos.config.fileExtension |
properties |
配置項對應的文件擴展名,目前支持 properties 和 yaml(yml) |
獲取配置超時時間 | spring.cloud.nacos.config.timeout |
3000 |
客戶端獲取配置的超時時間(毫秒) |
接入點 | spring.cloud.nacos.config.endpoint |
地域的某個服務的入口域名,通過此域名可以動態地拿到服務端地址 | |
命名空間 | spring.cloud.nacos.config.namespace |
常用場景之一是不同環境的配置的區分隔離,例如開發測試環境和生產環境的資源(如配置、服務)隔離等 | |
AccessKey | spring.cloud.nacos.config.accessKey |
當要上阿里雲時,阿里雲上面的一個雲賬號名 | |
SecretKey | spring.cloud.nacos.config.secretKey |
當要上阿里雲時,阿里雲上面的一個雲賬號密碼 | |
Nacos Server 對應的 context path | spring.cloud.nacos.config.contextPath |
Nacos Server 對外暴露的 context path | |
集群 | spring.cloud.nacos.config.clusterName |
配置成Nacos集群名稱 | |
共享配置 | spring.cloud.nacos.config.sharedDataids |
共享配置的 DataId, "," 分割 | |
共享配置動態刷新 | spring.cloud.nacos.config.refreshableDataids |
共享配置中需要動態刷新的 DataId, "," 分割 | |
自定義 Data Id 配置 | spring.cloud.nacos.config.extConfig |
屬性是個集合,內部由 Config POJO 組成。Config 有 3 個屬性,分別是 dataId , group 以及 refresh
|
7. Nacos Config Actuator Endpoint
Nacos Config 內部提供了一個 Endpoint, 對應的 Endpoint ID 為 nacos-config
,其 Actuator Web Endpoint URI 為 /actuator/nacos-config
注:使用 Nacos Config Spring Cloud 1.x 版本的話,其 URI 地址則為
/nacos-config
其中,Endpoint 暴露的 json 中包含了三種屬性:
- NacosConfigProperties: 當前應用 Nacos 的基礎配置信息
- RefreshHistory: 配置刷新的歷史記錄
- Sources: 當前應用配置的數據信息
由於 Aliyun Java Initializr 所生成的應用工程默認激活 Spring Boot Actuator Endpoints(JMX 和 Web),具體配置存放在 application.properties
文件中,同時,Actuator Web 端口設置為 8081,內容如下:
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
# Actuator Web 訪問端口
management.server.port=8081
因此,應用 nacos-config-sample 無需調整,直接訪問:http://127.0.0.1:8081/actuator/nacos-config,服務響應的內容如下:
{
"NacosConfigProperties": {
"serverAddr": "127.0.0.1:8848",
"username": "",
"password": "",
"encode": null,
"group": "DEFAULT_GROUP",
"prefix": null,
"fileExtension": "properties",
"timeout": 3000,
"maxRetry": null,
"configLongPollTimeout": null,
"configRetryTime": null,
"enableRemoteSyncConfig": false,
"endpoint": null,
"namespace": null,
"accessKey": null,
"secretKey": null,
"contextPath": null,
"clusterName": null,
"name": null,
"sharedConfigs": null,
"extensionConfigs": null,
"refreshEnabled": true,
"sharedDataids": null,
"refreshableDataids": null,
"extConfig": null,
"configServiceProperties": {
"secretKey": "",
"namespace": "",
"username": "",
"enableRemoteSyncConfig": "false",
"configLongPollTimeout": "",
"configRetryTime": "",
"encode": "",
"serverAddr": "127.0.0.1:8848",
"maxRetry": "",
"clusterName": "",
"password": "",
"accessKey": "",
"endpoint": ""
}
},
"RefreshHistory": [
],
"Sources": [
{
"lastSynced": "2020-09-14 11:11:37",
"dataId": "nacos-config-sample.properties"
},
{
"lastSynced": "2020-09-14 11:11:37",
"dataId": "nacos-config-sample"
}
]
}
對文檔有任何問題,請在評論區留言!