一、什么是Nacos
英文全稱Dynamic Naming and Configuration Service,Na為naming/nameServer即注冊中心,co為configuration即注冊中心,service是指該注冊/配置中心都是以服務為核心
Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理
二、Nacos原理
Nacos注冊中心分為server與client,server采用Java編寫,為client提供注冊發現服務與配置服務。而client可以用多語言實現,client與微服務嵌套在一起,nacos提供sdk和openApi,如果沒有sdk也可以根據openApi手動寫服務注冊與發現和配置拉取的邏輯
Nacos服務領域模型主要分為命名空間、集群、服務。在下圖的分級存儲模型可以看到,在服務級別,保存了健康檢查開關、元數據、路由機制、保護閾值等設置,而集群保存了健康檢查模式、元數據、同步機制等數據,實例保存了該實例的ip、端口、權重、健康檢查狀態、下線狀態、元數據、響應時間
注冊中心原理

配置中心原理
三、 Nacos使用方法
創建命名空間
不同的命名空間邏輯上是隔離的,不特殊設置的情況下,服務不會跨命名空間請求,命名空間主要的作用是區分服務使用的范圍,比如開發、測試、生產、灰度可以分別設置四個命名空間來互相隔離
如圖所示,在控制台的 服務管理-命名空間-新建命名空間按鈕可以創建新的命名空間,命名空間創建后,會在列表顯示命名空間ID,這個ID后面會用在服務的配置文件中
在服務上配置注冊、配置中心
以springcloud為例,首先用maven導入nacos clinet的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>0.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
先導入springcloud的alibaba-nacos-config和alibaba-nacos-discovery兩個依賴,這兩個依賴是用於nacos clinet與cloud結合的工具,0.2.x對應springboot 2.x.x ,0.1.x對應springboot 1.x.x。這兩個組件可以和各種版本的nacos-client結合。把其中的nacos-clinet依賴給排除,引入想要引入的nacosclinet版本,如下:
<!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.0.1</version> </dependency>
在bootstrap.properties上添加配置中心的配置,如果springboot啟動類沒有@EnableDiscover注解則加上,完成如上更改,即可使用Nacos注冊/配置服務
spring.cloud.nacos.discovery.server-addr=nacos.e.189.cn:80
spring.cloud.nacos.discovery.namespace=命名空間id
通過配置更改動態刷新參數
普通application參數在配置中心直接配置皆可,如果需要可以動態刷新的配置,需要在相應類上加上@RefreshScope注解,示例如下,當在nacos配置中心更改配置后,方法getId的值也會刷新
@RefreshScope public class IdEntity { @Value("${id}") private int id; public int getId(){ return this.id; } }
配置中心參數修改/設置
如下兩張圖:在nacos控制台的 配置管理-配置列表中頂部選擇相應的命名空間,點擊列表右上角的加號新增配置,Data ID 為 項目名-{spring.profiles.active}.properties,Group如果在bootstrap.properties中不指定則填默認的DEFAULT_GROUP,描述寫該配置的描述,配置內容填寫Properties格式或者Yaml格式

nacos其他功能使用與介紹
控制台手動上下線實例
在控制台的服務管理-服務列表選擇一個服務點擊詳情,在下方的集群列表可以看到有上線/下線按鈕,點擊即可以對該實例執行上線/下線操作,下線后的實例不會被請求

配置實例權重
可以通過手動配置權重來控制流量,當一個集群內兩個實例,權重越高,到達該實例的請求比例越多,權重的初始值是1

配置保護閾值
保護閾值的范圍是0~1
服務的健康比例=服務的健康實例/總實例個數
當服務健康比例<=保護閾值時候,無論實例健不健康都會返回給調用方
當服務健康比例>保護閾值的時候,只會返回健康實例給調用方
在服務管理-服務列表選擇一個服務點擊詳情可以配置

四 Nacos作為注冊中心
我們創建一個springcloud父工程,只包含web依賴。然后基於該父工程,分別創建服務提供者Provider和消費者Consumer工程。
服務提供者Provider
需要的依賴如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.1</version>
</dependency>
配置文件如下:
server: port: 8091 spring: application: name: nacos-provider cloud: nacos: server-addr: localhost:8848
創建一個controller來模擬Provider對外提供服務:
@RestController public class HelloController { @GetMapping("/getHello") public String getHello(){ return "hello from nacos provider!"; } }
到此,我們服務提供者就創建好了,在localhost:8091端口等待被調用提供服務
服務消費者Consumer
需要的依賴如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.0.3</version>
</dependency>
配置文件如下:
server: port: 8092 spring: application: name: nacos-consumer cloud: nacos: server-addr: localhost:8848
創建一個Controller類,對外提供調用的接口,然后在Controller中通過OpenFeign轉發調用請求給到Provider
@RestController public class HelloController { @Autowired private FeignService feignService; @GetMapping("/getHello") public String getHello(){ return feignService.getHello(); } }
@FeignClient("nacos-provider")
public interface FeignService {
@GetMapping("/getHello")
String getHello();
}
如上Service表示需要請求注冊中心中服務名稱為nacos-provider的/getHello接口。最后,我們需要在啟動類上加上啟動注解
@EnableFeignClients @EnableDiscoveryClient @SpringBootApplication public class DiscoveryConsumerApplication { public static void main(String[] args) { SpringApplication.run(DiscoveryConsumerApplication.class, args); } }
到此,消費者Consumer也創建好了,在localhost:8092提供調用服務。我們訪問Consumer的/getHello接口,獲得的返回內容為:
hello from nacos provider!
五 Nacos作為配置中心
入門案例
首先我們需要引入必要的依賴包:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
我們在啟動配置文件bootstrap.properties中配置如下的內容:
spring.application.name=nacos-provider
spring.cloud.nacos.server-addr=127.0.0.1:8848
然后我們創建一個Controller就可以演示從遠端獲取配置內容了:
@RefreshScope @RestController public class ConfigController { @Value("${provider.name}") private String providerName; @GetMapping("/getDevConfig") public String getDevConfig(){ return this.providerName; } }
代碼層面的示例都已經寫好了,我們在遠端nacos服務端,切換到配置管理的配置列表界面,需要點擊+號新建一個:
- DataID,該字段的取名是有規則的,一般而言分為三個部分,
{1}-{2}.{3},其中第一部分應該和剛才本地bootstrap.properties中配置的spring.application.name完全一樣;第二部分表示生效的環境名稱,比如dev、stg等;第三部分表示配置文件后綴,只支持properties或者yaml類型。在這里,我們的值應該為nacos-provider.properties; - Group,這里先設置默認的
DEFAULT_GROUP即可; - 配置內容,把需要保存在遠端Nacos的配置內容寫在里面即可,這里為
provider.name=nacos123;
配置點擊發布后,我們啟動本地的nacos-provider服務,訪問Controller,就會發現讀取到了nacos123的配置內容。
配置文件的環境區分
在實際使用時,我們一般都是區分dev、stg、prd三套環境來維護各個環境的配置文件內容的。在這樣的情況下,我們的應用程序如何讀取不同環境下的配置內容呢
通過profile區分
首先我們在Nacos配置中心再增加兩個DataID,分別如下:
# nacos-provider-dev.properties
# DEFAULT_GROUP
provider.name=nacos-dev
# nacos-provider-stg.properties
# DEFAULT_GROUP
provider.name=nacos-stg
為了讓這兩個配置文件生效,我們在本地應用端的bootstrap.properties中指定生效配置文件的環境名稱即可:
spring.application.name=nacos-provider spring.cloud.nacos.server-addr=127.0.0.1:8848 spring.profiles.active=dev # spring.profiles.active=stg
再重啟我們的應用,就能讀取到各自環境的配置文件了
通過namespace區分
默認我們會到public這個命名空間下去讀取配置文件,此時我們新建兩個命名空間,分別命名為dev和stg,然后將public命名空間下的nacos-provider.properties克隆到dev和stg命名空間下,並修改provider.name的配置內容:
# namespace dev
provider.name=nacos-dev-123
# namespace stg
provider.name=nacos-stg-123
我們在本地的應用中增加一個配置項,表明想要引用的namespace:
spring.cloud.nacos.config.namespace=0a6be74a-426e-45eb-8531-6d7230f26af6
然后重啟應用,就能讀取到對應namespace下面的配置內容了
加載多配置文件
默認情況下,本地應用會去nacos服務端讀取對應namespace下面的以應用名稱開頭的配置文件,在本例子中就是nacos-provider.properties,因為我們本地應用配置的spring.application.name=nacos-provider,在實際開發中,往往會有多個配置文件,那么如何同時加載多個配置文件中的配置內容呢?
首先,我們在public命名空間下再新建兩個配置文件:
# redis.properties
redis.server=127.0.0.1
# mq.properties
mq.nameserver=localhost
同時,我們需要在本地項目的bootstrap.properties配置文件中增加如下的配置內容:
spring.cloud.nacos.config.ext-config[0].data-id=redis.properties spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP spring.cloud.nacos.config.ext-config[0].refresh=true spring.cloud.nacos.config.ext-config[0].data-id=mq.properties spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP spring.cloud.nacos.config.ext-config[0].refresh=true
對應的yml配置形式為:
spring: cloud: nacos: config: extension-configs: - refresh: true group: DEFAULT_GROUP data-id: redis.properties - refresh: true group: DEFAULT_GROUP data-id: mq.properties
然后,修改我們的controller,引用nacos服務器上的不同配置文件里面的配置項:
@RefreshScope @RestController public class ConfigController { @Value("${provider.name}") private String providerName; @Value("${redis.server}") private String redisServer; @Value("${mq.nameserver}") private String mqServer; @GetMapping("/getDevConfig") public String getDevConfig() { return this.providerName + "/" + this.redisServer + "/" + this.mqServer; } }
重啟應用后,就能成功訪問不同配置文件里面的配置項了。
配置文件的分組區分
如上我們注意到,分組Group一直都是DEFAULT_GROUP,其實我們可以在不同的Group里面創建相同名稱的配置文件。比如在微服務環境中,多個微服務組件都有redis.properties的配置文件,那么如何區分哪個微服務該使用哪個Group下面的配置文件呢,其實也很簡單,只要在配置文件中指定Group即可。
本實例比較簡單,就不演示了,其實對於同一個應用也可以讀取不同Group下面的配置文件配置內容,我們完全也可以用Group來作為dev、stg和prd的區分。
總之,Nacos為我們提供了三個維度來做區分,即profile、namespace和Group,開發者可以靈活應用來做自己想要的區分。
共享配置
很多時候,多個微服務中有相同的配置內容,比如大家連結的是同一個redis服務,同一個mq服務,那么就需要在各自的配置文件中都寫上相同的配置內容,顯得比較繁瑣,我們完全可以將這些共同的配置內容抽取出來,形成另一個配置文件,然后大家共享它。
比如,我們在public命名空間下新建DEFAULT_GROUP的配置文件share.properties:
provider.share=share123
然后本地配置文件中新增如下配置內容:
# 如果有多個共享配置文件,相互之間用逗號分隔即可
spring.cloud.nacos.config.shared_dataids: share.properties
spring.cloud.nacos.config.refreshable-dataids: share.properties
然后在Controller中增加共享配置的讀取內容,此處就省略了,重啟應用就可以生效了。
注意,如果共享配置不是DEFAULT_GROUP下面的,就不能使用如上的方式,而是采用2.3節中講述的方式
配置內容的優先級
有些時候,我們在加載的配置文件中都配置了同一個配置項的值,而且相互之間都不相同,那么本地應用最終以哪個配置文件中的內容為准呢
- A:使用
spring.cloud.nacos.config.prefix、spring.cloud.nacos.config.file-extension、spring.cloud.nacos.config.group這幾個參數拼接出來的配置文件; - B:使用2.3節中extension-configs指定的配置間件;
- C:使用2.5節中共享配置指定的配置文件;
- D:本地配置的配置內容;
優先級順序為:D>A>B>C
