天天看點

Spring Cloud Alibaba 分布式配置config external configuration1、Data Id 在預設的組 DEFAULT_GROUP,不支援配置的動态重新整理2、Data Id 不在預設的組,不支援動态重新整理3、Data Id 既不在預設的組,也支援動态重新整理配置支援共享的 Data Id配置 Data Id 所在分組,預設預設 DEFAULT_GROUP配置Data Id 在配置變更時,是否動态重新整理,預設預設 falseActuator Web 通路端口

Spring Cloud Alibaba 分布式配置

  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 代替對應的元件。

  1. 學習目标

    使用 Nacos Config 作為 Spring Cloud 分布式配置

    使用 Nacos Config 實作 Bean 動态重新整理

    了解 Nacos Config 進階配置

  2. 詳細内容

    快速上手:使用 Nacos Config 作為外部化配置源

    多檔案擴充名支援:以 YAML 檔案擴充名為例,讨論 Nacos Config 多檔案擴充名支援

    動态配置更新:示範 @RefreshScope 特性,實作 Bean 動态重新整理

    自定義擴充:自定義 namespace、Group 以及 Data Id 的配置擴充

    運維特性:示範 Nacos Config 進階外部化配置以及 Endpoint 内部細節

  3. 快速上手

    4.1 如何引入 Nacos Config 支援分布式配置

    Nacos Config 引入的方式同樣也有兩種,即 Aliyun Java Initializr 引入和 Maven pom.xml 依賴。官方推薦使用 Aliyun Java Initializr 方式引入 Nacos Discovery,以便簡化元件之間的依賴關系。

4.1.1 [偷懶] 直接在沙箱裡檢視應用代碼

點選 連結,直接通路沙箱環境,這裡會有為你準備好的案例代碼_。

4.1.2 [簡單] 通過 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”,如下所示:

image.png

同上元件操作,增加 “Spring Web” 和 “Spring Boot Actuator” 元件:

image.png

元件選擇後,點選 “生成” 高亮按鈕。随後,平台将生成一個名為 “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 元件依賴的版本,它們的版本定義在 元素中,即 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.3 [進階] 通過 Maven pom.xml 依賴 Nacos Config

如果要在您的項目中使用 Nacos 來實作服務注冊/發現,使用 group ID 為 com.alibaba.cloud和 artifact ID 為 spring-cloud-starter-alibaba-nacos-config的 starter。

com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config 該聲明方式同樣需要聲明 com.alibaba.cloud:spring-cloud-alibaba-dependencies,内容與上小節相同,在此不再贅述。下一節将讨論如何使用 Nacos Config 支援分布式配置。

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),選擇 “配置管理/配置清單”:

undefined

由于服務是公共免費的,為了做好隔離,是以分布式配置的功能,請選擇在 sandbox-configuration 的命名空間下操作。

具體啟動方式參考 Nacos 官網。

關于更多的 Nacos Server 版本,可以從 release 頁面 下載下傳最新的版本。

4.2.2 添加 Nacos 配置

點選“配置清單”頁面右側的 “+” 号(紅色箭頭所指):

undefined

浏覽器跳轉新頁面,并填充内容如下:

image.png

其中,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 目錄下建立名為 “bootstrap.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 位址必須配置在 bootstrap.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 節。

  1. 使用 Nacos Config 實作 Bean 動态重新整理

    Nacos Confg 支援标準 Spring Cloud @RefreshScope特性,即應用訂閱某個 Nacos 配置後,當配置内容變化時,Refresh Scope Beans 中的綁定配置的屬性将有條件的更新。所謂的條件是指 Bean 必須:

必須條件:Bean 的聲明類必須标注 @RefreshScope

二選一條件:

屬性(非 static 字段)标注 @Value

@ConfigurationPropertiesBean

除此之外,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,如下圖:

undefined

undefined

本文中,其他的基于http通路的步驟類似,後面不在贅述

本次請求結果中的 user name 和 age 資料與應用啟動時的一緻,因為此時 Nacos Server 中的配置資料沒變化。

随後,通過 Nacos 控制台調整 nacos-config-sample.properties 配置,将 user.age 從 90 變更為 99:

image.png

點選“釋出”按鈕,觀察應用日志變化(部分内容被省略):

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 接收到服務端配置變更時,對應的 @RefreshScopeBean 生命周期回調方法會被調用,并且是先銷毀,然後由重新初始化。本例如此設計,無非想提醒讀者,要意識到 Nacos Config 配置變更對 @RefreshScopeBean 生命周期回調方法的影響,避免出現重複初始化等操作。

注: Nacos Config 配置變更調用了 Spring Cloud API ContextRefresher,該 API 會執行以上行為。同理,執行 Spring Cloud Acutator Endpoint refresh也會使用 ContextRefresher。

通過上述讨論,相信讀者已對 Nacos 配置變更操作相當的熟悉,後文将不再贅述相關配置。接下來繼續讨論 @ConfigurationPropertiesBean 的場景。

5.2 使用 Nacos Config 實作 @ConfigurationPropertiesBean 屬性動态重新整理

在應用 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實作,主要改動點:

激活 @ConfigurationPropertiesBean @EnableConfigurationProperties(User.class)

通過 @Autowired依賴注入 UserBean

使用 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 配置變更會影響 @RefreshScopeBean 的生命周期方法回調。同理,如果為 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]

不難發現, UserBean 的生命周期方法不僅被調用,并且仍舊是先銷毀,再初始化。那麼,這個現象和之前看到的 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()方法,通過 NacosConfigManagerBean 擷取 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支援屬性粒度的更新。

  1. 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 屬性是個集合,内部由 ConfigPOJO 組成。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”

}

]

}