副本介紹
官方:一個更易于構建云原生應用的動態(tài)服務發(fā)現(xiàn)(Nacos Discovery)、服務配置(Nacos Config)和服務管理平臺
集 注冊中心+配置中心+服務管理 于一身
Nacos 的關鍵特性包括:
- 服務發(fā)現(xiàn)和服務健康監(jiān)測
- 動態(tài)配置服務
- 動態(tài) DNS 服務
- 服務及其元數(shù)據(jù)管理
第一關:初識Nacos注冊中心
注冊中心演變及其設計思想





- 服務啟動的時候,調用注冊接口,將服務注冊到注冊表里
- 服務停止的時候,調用注銷接口,將服務從注冊表里剔除
- 服務運行的時候,會定時發(fā)送心跳,根據(jù)結果對注冊表里的數(shù)據(jù)進行操作
心跳機制的作用有什么呢?
可能服務每隔一段時間,向注冊中心發(fā)送一次心跳。一定時間內(15s)注冊中心沒有收到心跳,就把status狀態(tài)改為down,再過一段時間(30s)還是沒有收到該服務的心跳,就需要把該服務從注冊表里剔除出去。
第二關:Nacos Server 部署
安裝nacos的時候,需要考慮到整體的版本選擇問題,包括:SpringBoot 的版本,SpringCloud 的版本,SpringCloud Alibaba 的版本,SpringCloud Alibaba 中各項技術的版本
版本之間的依賴可參考SpringCloud Alibaba 官方文檔提供的關系

本機安裝 Nacos。
- 直接進入bin目錄。
sh startup.sh -m standalone (standalone 是啟動單機模式,nacos默認的是集群模式)
- 修改/nacos/conf/application.propertile文件,從里面配置我們自己的數(shù)據(jù)庫(集群必須配置,單機模式如果不配置的話,nacos會默認使用內存)
- 也可以直接修改 startup.sh 文件,把里面的mode 從 cluster 直接改成 standalone (這樣第一步就不需要跟后面的命令了)
Docker 安裝 Nacos
-
查找docker鏡像,拉取鏡像
docker拉取鏡像 -
啟動容器
docker run -d --name nacos -p 8848:8848 -e MODE=standalone -v /nacos/logs:/home/nacos/logs --restart=always nacos/nacos-server介紹一下各個參數(shù)
-d 后臺運行
-p 端口映射。外部訪問端口:內部映射端口
-e 環(huán)境變量設置 (多個環(huán)境變量的使用 -e xxx=xxx -e xxx=xxx -e xxx=xxx)
-v 某個容器的目錄:映射到服務器上的目錄
上述啟動nacos 是單機模式,沒有指定數(shù)據(jù)庫,會默認使用內存。當我們需要指定數(shù)據(jù)庫的時候,可以通過 -e 配置環(huán)境變量,也可以學習使用docker-compose進行簡化處理(需要注意的是當使用集群模式,必須使用外部數(shù)據(jù)庫)
查看容器的輸出日志
docker logs --since 容器id進入容器
進入容器
第三關:Nacos核心功能之服務發(fā)現(xiàn)
Nacos Discovery
服務注冊:Nacos Client會通過發(fā)送REST請求的方式向Nacos Server注冊自己的服務,提供自身的元數(shù)據(jù),比如ip地址、端口等信息。Nacos Server接收到注冊請求后,就會把這些元數(shù)據(jù)信息存儲在一個雙層的內存Map中。
服務心跳:在服務注冊后,Nacos Client會維護一個定時心跳來持續(xù)通知Nacos Server,說明服務一直處于可用狀態(tài),防止被剔除。默認5s發(fā)送一次心跳。
服務同步:Nacos Server集群之間會互相同步服務實例,用來保證服務信息的一致性。 leader raft
服務發(fā)現(xiàn):服務消費者(Nacos Client)在調用服務提供者的服務時,會發(fā)送一個REST請求給Nacos Server,獲取上面注冊的服務清單,并且緩存在Nacos Client本地,同時會在Nacos Client本地開啟一個定時任務定時拉取服務端最新的注冊表信息更新到本地緩存
服務健康檢查:Nacos Server會開啟一個定時任務用來檢查注冊服務實例的健康情況,對于超過15s沒有收到客戶端心跳的實例會將它的healthy屬性置為false(客戶端服務發(fā)現(xiàn)時不會發(fā)現(xiàn)),如果某個實例超過30秒沒有收到心跳,直接剔除該實例(被剔除的實例如果恢復發(fā)送心跳則會重新注冊
Nacos 的經(jīng)典模型
一共由三層構成:
- Namespace 命名空間
- Group 組
- Service/DataId 服務/配置

Nacos 的分層是用來做什么的呢?
核心作用就兩個字 - 【隔離】
最經(jīng)典的使用場景就是 我們通過Namespace去劃分開發(fā)環(huán)境,然后通過Group在細分每個環(huán)境里需要隔離的服務/子系統(tǒng)。
Nacos Discovery實踐 - 創(chuàng)建服務 provider
Provider 的實現(xiàn)目標:
- 整合 Nacos
- 提供一個簡單的接口
如何整合Nacos
- 添加Nacos Discovery 的依賴
- 在配置文件中指定 Nacos Server 的地址
- 添加 @EnableDiscoveryClient 注解,開啟服務發(fā)現(xiàn)
修改 pom.xml 文件
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>provider</artifactId>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
創(chuàng)建配置文件bootstrap.yml ,添加Nacos配置
( Nacos-docker 是docker容器的名稱,會有對應的ip地址)
spring:
application:
name: provider
cloud:
nacos:
discovery:
server-addr: ${NACOS-HOST:nacos-docker}:${NACOS-PORT:8848}
namespace: ${REGISTER_NAMESPACE}
給啟動類添加注解,開啟nacos服務發(fā)現(xiàn)
...
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
之后我們啟動Provider 服務,啟動完成后,打開Nacos 控制臺中的服務列表頁面就可以看到我們啟動的服務了

Nacos Discovery實踐 - 創(chuàng)建服務 consumer
Consumer 的實現(xiàn)目標:
- 整合 Nacos (同上)
- 提供一個簡單的接口,在接口中調用 Provider 的接口
使用restTemplate 進行調用
@Configuration
public class ConsumerConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
public class TestController {
// 引入 LoadBalancerClient,負責負載均衡
@Autowired
private LoadBalancerClient loadBalancerClient;
// 引入 RestTemplate
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(@RequestParam String name) {
// 通過 loadBalancerClient 獲取名為 "provider" 服務的一個實例
ServiceInstance serviceInstance =
loadBalancerClient.choose("provider");
// 取得實例的 URI
URI instanceUri = serviceInstance.getUri();
// 使用 RestTemplate 發(fā)起請求調用
String result = restTemplate.getForObject(
instanceUri + "/hello?name=" + name,
String.class);
return "[consumer] " + result + "!";
}
}
在平時開發(fā)中,我們這邊的調用會使用 openFeign 或者 Dubbo 底層也都是通過服務名,從而負載均衡到對應的服務上
第四關:Nacos 核心功能之分布式配置
Nacos Config
傳統(tǒng)配置文件的弊端
- 維護性 多個服務的公共配置發(fā)生變化的時候,需要把所有微服務的配置文件更改
- 時效性 當更改了配置文件,需要重啟服務
- 安全性 所有敏感配置都在代碼里,容易出問題(不發(fā)工資就清庫 - -)。 同時Nacos 有權限控制,可以通過不同的環(huán)境給員工配置不同的賬號
分布式配置到底有什么用處呢?
我們平時都是把配置寫在應用的配置文件里的是吧,這樣做肯定是沒毛病的,但就是管理起來比較麻煩。
比如一個服務部署了10個實例,他們的配置都是一樣的是吧,如果想改動其中的一個配置的值,該怎么做?
答案是:修改服務中配置文件,然后重新部署10個實例是吧。
但這樣做是不是很麻煩???如果修改配置這個動作比較頻繁,可就相當悲催了。而且還需要重新部署服務。
要是能夠動態(tài)修改配置就好了,不用重新部署就方便多了。這就需要能夠實現(xiàn)配置的【動態(tài)刷新】。假設動態(tài)配置可以實現(xiàn),但是每個實例中修改同一個配置還是挺麻煩的。如果能夠在一個地方改動配置之后,所有相關實例能夠自動獲取都最新的值,然后自動生效,那就完美啦,這就需要實現(xiàn)配置的【共享配置】。
所以我們期待兩個功能:
- 配置動態(tài)刷新
- 統(tǒng)一修改配置,所有實例自動獲取最新值
而Nacos Config 分布式配置功能就可以幫我們實現(xiàn)這2個愿望,完美。

Nacos Config實踐
實踐目標
- 創(chuàng)建一個服務,使用本地配置,然后整合Nacos Config,改用 Nacos 中的配置
- 實現(xiàn)配置動態(tài)刷新
實踐步驟
- 在 Nacos 中新建配置
- 給服務中添加 Nacos Config 依賴
- 給服務中創(chuàng)建配置文件 bootstrap.yaml
在 Nacos 中新建配置
新建配置 Data ID 填寫 demo-config.yml
Group不用動,默認是DEFAULT_GROUP
配置格式. YAML

改造服務,給服務添加依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
補充 bootstrap.yaml 配置文件
為什么要用bootstrap.yaml ?
是因為bootstrap.yaml 的優(yōu)先級高于 application.yaml, 在應用啟動的時候就可以讀取到了,所以需要在其中配置服務最基礎的信息,例如服務名、Nacos Config 的地址,這樣就可以獲取Nacos 中的配置了。
server:
port: 8080
spring:
application:
name: demo-config
cloud:
nacos:
config:
server-addr: 192.168.0.5:8848
file-extension: yml
其中定義了服務端口、服務名、Nacos Config 的連接地址,這都是很好理解的,但最后一行的 "file-extension: yml" 是干什么的呢?
這就涉及到 Nacos Config 的配置命名規(guī)則。
回想一下,之前我們在 Nacos 中新建了一個配置,"Data ID" 命名為了 "demo-config.yml" 是吧。

那么為什么這么命名?我們的服務又如何關聯(lián)到這個配置呢?
我們把 "demo-config.yml" 這個名字對照 bootstrap.yaml 的內容看一下:

同時Nacos Config 也是支持 profiles.active 的,

由此可看出,Nacos 中配置 DataID 的命名規(guī)則是:
[application.name]-[profiles.active] . [file-extension]
配置動態(tài)刷新
經(jīng)過上面的改造,已經(jīng)可以讀取 Nacos 配置中心里面的配置了,同時是可以自動刷新的。
「特殊的情況1」但是如果通過@Value注解獲取配置文件里數(shù)據(jù),在 Nacos 中修改配置的值之后,服務是不能獲知的。所以還需要加一點東西來實現(xiàn)配置的動態(tài)刷新。方法極其簡單,添加 @RefreshScope 注解即可,如下:
@RefreshScope
@RestController
public class TestController {
...
}
「特殊的情況2」公共的配置文件(共享配置文件)。shared-configs 不會自動刷新,需要用戶自己配置刷新 ( yml數(shù)組的兩種形式分別在下面展示 )

「以下配置網(wǎng)上抄錄,注釋齊全,可根據(jù)自己實際情況修改,非常nice」
spring:
application:
# 服務名
name: pearl-test
cloud:
nacos:
config:
# 是否開啟配置中心 默認true
enabled: true
# 配置中心地址
server-addr: localhost:8848
# 配置文件后綴
file-extension: yml
# 配置對應的分組
group: PEARL_GROUP
# 命名空間 常用場景之一是不同環(huán)境的配置的區(qū)分隔離,例如開發(fā)測試環(huán)境和生產(chǎn)環(huán)境的資源(如配置、服務)隔離等
namespace: ba42e722-81aa-48f1-9944-9dca57d5f396
# Nacos 認證用戶
username: nacos
# Nacos 認證密碼
password: 123456
# 支持多個共享 Data Id 的配置,優(yōu)先級小于extension-configs,自定義 Data Id 配置 屬性是個集合,內部由 Config POJO 組成。Config 有 3 個屬性,分別是 dataId, group 以及 refresh
shared-configs[0]:
data-id: pearl-common.yml # 配置文件名-Data Id
group: PEARL_GROUP # 默認為DEFAULT_GROUP
refresh: false # 是否動態(tài)刷新,默認為false
shared-configs[1]:
data-id: pearl-custom.yml
group: PEARL_GROUP
refresh: true
Nacos Config 權限控制
要想實現(xiàn)權限控制,除了對應角色的權限處理之外。還需要修改nacos的配置文件。
編輯文件: vim nacos/conf/application.properties
修改 nacos.core.auth.enabled = true (默認是false)

