目录
[Nacos 简介](#Nacos 简介)
[Nacos 安装](#Nacos 安装)
[启动 Nacos](#启动 Nacos)
[使用 Nacos](#使用 Nacos)
[服务注册 / 服务发现](#服务注册 / 服务发现)
[引入 Spring Cloud Alibaba 依赖](#引入 Spring Cloud Alibaba 依赖)
[引入 nacos 依赖和 Load Balance 依赖](#引入 nacos 依赖和 Load Balance 依赖)
[配置 Nacos 地址](#配置 Nacos 地址)
[开启 Nacos 负载均衡策略](#开启 Nacos 负载均衡策略)
[Nacos 服务实例类型](#Nacos 服务实例类型)
[Nacos 服务实例类型不允许改变](#Nacos 服务实例类型不允许改变)
[Nacos 环境隔离](#Nacos 环境隔离)
[创建 namespace](#创建 namespace)
[配置 namespace](#配置 namespace)
[Nacos 配置中心](#Nacos 配置中心)
[配置 bootstrap.yml](#配置 bootstrap.yml)
[Data Id](#Data Id)
[修改数据库,Nacos 等相关配置](#修改数据库,Nacos 等相关配置)
[Nacos 和 Eureka 的区别](#Nacos 和 Eureka 的区别)
Nacos 简介
随着 Eureka 2.0 的宣布闭源,阿里 Nacos 宣布开源,快速成为国内最受关注的开源产品。
在最初开源时,Nacos 选择进行内部三个产品合并统一开源(Configserver 非持久注册中心,VIPServer 持久化注册中心,Diamond 配置中心)。定位:一个更易于构建云原生应用的动态服务发现,配置管理和服务管理平台。所以 Nacos 是一个注册中心组件,但又不仅仅只是一个注册中心组件。
github 仓库:https://github.com/alibaba/nacos
Nacos 安装
在学习阶段采用单机安装即可
下载安装包
在官网中找到下载页面进行下载
这里使用 2.2.3 版本
下载地址:https://github.com/alibaba/nacos/releases/tag/2.2.3

Windows
将压缩包解压到任意非中文的目录下

目录介绍:
bin:Nacos 的启停脚本

startup.cmd:windows 平台下的启动脚本
startup.sh:Linux 平台下的启动脚本
shutdown.cmd:windows 平台下的停止脚本
shutdown.sh:Linux 平台下的停止脚本
conf:存放 Nacos 的相关配置
targert:存放 Nacos 应用的相关 jar 包
修改单机模式
Nacos 默认的启动方式是集群,启动前需要修改配置为单击模式
-
使用文本编辑器(记事本即可)打开 startup.cmd
-
在 26 行左右,将启动模式由 cluster 修改为 standalone

保存后关闭文件
启动 Nacos
进入 bin 目录,双击 startup.cmd 即可

访问 Nacos 主页:http://127.0.0.1:8848/nacos
出现以下界面,表示 Nacos 启动成功

常见问题:
Nacos 启动后,目录会多出一个 logs 的文件夹
这个文件夹会记录以下 Nacos 的相关日志。其中 Nacos 的报错日志就在 logs/nacos.log
如果以集群模式启动,就会有如下报错日志:

Nacos 的默认端口号为 8848,如果该端口号被其他应用占用,启动也会报错:

解决办法:
- 关闭端口号为 8848 的进程:
打开 cmd,查找进程,输入命令:
杀掉进程
- 修改 Nacos 的端口号
进入 confg 目录下的 application.properties
23 行左右,将 server.port 进行修改即可

Linux
准备安装包
将提前下载号的压缩包上传在服务器的某个目录中,例如可以创建目录:mkdir naoce-server
然后解压压缩包:
unzip nacos-server-2.2.3.zip
如果第一次使用解压压缩包,未安装 upzip 命令,需要更新 apt 后进行安装
apt update
apt-get install unzip
解压后目录如下:

和 windows 中是一样的
单机模式启动
进入 nacos/bin 目录

输入命令:
bash startup.sh -m standalone
// 用 bash(一种 Shell 解释器)去执行名为 startup.sh 的脚本文件,并通过 -m standalone 参数,指定以单机模式来运行程序。
启动成功后,将服务器的防火墙的对应端口号开放,访问 Nacos 连接:
http://IP:port/nacos

补充:8848 为 Nacos 的默认端口号,需要在服务器上开放。另外,再开放 Nacos 端口号 + 1000,和 Nacos 端口号 + 1001 的端口。比如端口号为 8848,则需要开放端口号为 9848 和 9849.
使用 Nacos
Nacos 是 Spring Cloud Alibaba 的组件,遵循 Spring Cloud 中定义的服务注册,服务发现规范。
与 Eureka 的主要差异在于:
-
Eureka 需要自己搭建一个服务,Nacos 不需要自己搭建服务,组件已经准备好了,只需启动即可
-
对应的依赖和配置不相同
服务注册 / 服务发现
引入 Spring Cloud Alibaba 依赖
在父工程的 pom 文件中的 <dependencyManagement> 引入 Spring Cloud Alibaba 的依赖

注意:Spring Boot 和 Spring Cloud 的版本存在一定的对应关系。Spring Cloud Alibaba 也遵循 Spring Cloud 的标准,在引入依赖的时候,主要要确认各个版本的对应关系。
官方文档:版本发布说明-阿里云Spring Cloud Alibaba官网
引入 nacos 依赖和 Load Balance 依赖
在 order-service 和 product-service 中引入 nacos 依赖和 Load Balance 依赖

配置 Nacos 地址
官方文档手册中的配置说明如下:

我们直接将云服务的 ip 和端口进行配置
分别在 order-service 和 product-service 进行配置

远程调用
将 IP 修改为项目名

然后为 restTemplate 添加负载均衡的注解 @LoadBalanced

启动服务
启动两个服务,观察 Naocs 的管理界面,发现 order-service 和 product-service 都注册在了 Nacos上

可以正常获取数据

启动多个服务,测试负载均衡
启动三个 product-service 服务

观察 Nacos控制台

多次访问接口,观察日志,发现可以实现负载均衡~~
常见问题
java.net.UnkonwnHostException

可能是未添加 LoadBalance 依赖

负载均衡
Nacos 支持多种负载均衡策略。
服务下线
当某一个节点上的接口性能较差,出现问题时,我们可以第一时间对该节点进行下线。


点击下线后,再次请求接口,会发现当前服务就没有请求了。
再次点击上线,该节点会继续收到请求。
权重配置
操作:找到对应节点,点击编辑,在弹出的窗口修改权重值。
每个节点的默认权重为 1

开启 Nacos 负载均衡策略
当我们开启了权重后,进行测试,发现权重较低的服务并没有向我们预期的那样接收到较少的服务。
这是由于 Spring Cloud LoadBalance 组件自身有负载均衡配置的方式,所以不支持 Nacos 的权重属性配置。
我们需要开启 Nacos 的负载均衡策略,让权重配置来生效。
参考文档:如何解决MSE Nacos上修改服务实例的权重不生效问题_微服务引擎(MSE)-阿里云帮助中心

配置负载均衡:在 yml 文件中开启 nacos 的负载均衡策略。(注意:需要在 order-service 服务调用方和 product-service 服务提供方都需要对 nacos 的负载均衡策略进行开启)

测试权重配置
对 nacos 堆顶负载均衡策略启动后,重新启动服务,多次访问接口,发现设置权重较小的服务接收到的请求明显比另外两个实少~~
注意:设置是权重是相比于整体流量所言的,即成千上万的流量最后均摊下的权重是我们设置的结果。局部流量并不是严格按照我们设置的比例进行分配的。
常见问题
在 Nacos 页面中设置权重之后,可能会弹出如下的弹窗警告

报错信息:caused:errCode:500,errMsg:dometadataoperationfailed;caused: com.alibaba.nacos.consistency.exception.ConsistencyException: The Raft Group [naming_instance_metadata] did not find the Leader node;caused: The Raft Group [naming_instance_metadata] did not find the Leader node;
原因:Nacos 采用 raft 算法来计算 Leader,并且会记录前一次启动的集群环境。当服务器 IP 改变时,会导致 raft 记录的集群地址失效,导致 Leader 出现问题。(网络环境发生变化的时候,IP 地址也会发生变化)
解决办法:先停止 Nacos 服务,然后删除 Nacos 根目录下的 data 文件下下的 protocol 文件夹,再重新启动 Naocs 服务~~

同集群优先访问
Nacos 将同一个机房内的实例,划分为一个集群。所以同集训优先访问,再一定程度上,可以理解为同机房的服务,优先访问。
微服务架构中,一个服务服务通常由多个实例共同提供服务,这些是可以部署在不同的机器上,这些机器可以分布在不同的机房,比如 product-service 服务
实例 1 和 实例 2 实例 3 分布在上海机房,实例 4 和实例 5 实例 6 分布在北京机房

微服务访问的时候,应尽量访问同机房的实例。当本机房内实例不可用的时候,才访问其他机房的实例。

给实例配置集群名称
- 为 product-service 设置集群名称
spring:
cloud:
nacos:
discovery:
server-addr: nacos ip 地址 + 端口号
cluster-name: SH #集群名称:上海集群
重启服务,观察 Nacos 控制台,SH 集群下面多了一个实例

设置 9091 端口号的实例,机房为 BJ
重启两个服务,观察 Nacos,BJ 集群下多了两个实例。

- 为 order-service 配置集群名称为:SH

重启服务,观察 nacos,发现 order-service 在 SH 集群

开启负载均衡策略
在 order-service 和 product-service 中开启 nacos 的负载均衡策略

测试
启动服务
-
对接口访问多次,观察日志,发现只有和 order-service 同集群(SH)的 9090 端口的实例收到了请求。
-
把 9090 端口的实例进行下线,再次访问接口,此时 9091 和 9092 端口的实例收到了请求~~
健康检查
两种健康检查机制
Nacos 作为注册中心,需要感知服务的健康状态,才能为服务方提供良好的服务。
Nacos 中提供了两种健康检查机制。
客户端主动上报机制:
客户端主动上报机制:
客户端上报机制:
客户端通过心跳上报方式告知服务端(nacos 注册中心)健康状态,默认心跳间隔 5 秒。
nacos 会在超过 15 秒未收到心跳后将实例设置为不健康状态,超过 30 秒将实例删除。
服务端反向探测机制:
nacos 主动弹指客户端健康状态,默认间隔为 20 秒
健康检查失败后实例会被标记为不健康,不会被立即删除。

Nacos 中的健康检查机制不能主动设置。
健康检查机制是和 Nacos 的服务实例类型强相关的。
Nacos 服务实例类型
Nacos 的服务类型分为临时实例和非临时实例。
临时实例:如果实例宕机超过一定时间,会从服务列表剔除。
非临时实例:如果实例宕机,不会从服务列表剔除,也可叫永久实例。
Nacos 对临时实例,采取的是客户端主动上报机制,对非临时实例,采用服务端反向探测机制。

将 order-service 服务注册为永久实例

重启服务,观察 Nacos 控制台

注意:Spring Boot 应用需要引入 spring-boot-start-actuator 才能提供 /actuator/health 接口,否则 Nacos 服务器主动探测的时候,会接收到 404 Not Found,判定为不健康。

且即使引入了 Actuator,默认情况下 /actuator/health 可能未暴露,需手动配置开放

如果我们未配置,则 Nacos 在间隔 20 秒,服务端反向探测的时候,健康检查失败,实例被标记为不健康,但是服务并不会被立即删除!

Nacos 服务实例类型不允许改变
设置服务类型实例,重启服务后可能会报错

原因:Nacos 会记录每个服务实例的 IP 和端口号,当发现 IP 和端口都没有发生变化的时候,Nacos 是不允许一个服务实例类型发生变化。比如从临时实例转为非临时实例。从非临时实例转化为临时实例。
解决办法:
-
停掉 nacos
-
删除 nacos 目录下的 /data/protocol/raft 信息,里面会保存应用实例的元数据信息。
Nacos 环境隔离
正式开发中,一个服务会分为开发环境,测试环境,生产环境
-
开发环境:开发人员用于开发的服务器,是最基础的环境。日志级别设置比较低,会有一些调试信息日志。
-
测试环境:测试人员用来进行测试的服务器,由开发环境到生产环境的过度。
-
生产环境:正式提供对外服务的环境,通常会关掉调试信息。
通常情况下,这几个环境之间是不能互相通信的。Nacos 提供了 namespace(命名空间)来实现环境的隔离。不同的 namespace 的服务不可见。
创建 namespace
默认环境下,所有服务都在同一个 namespace,名为 public

可以点击左侧命名空间,对 namespace 进行操作


配置 namespace
namespace 创建完之后,对服务进行配置

修改 order-service 的命名空间

这里的 namespace 与 nacos 中提供的命名空间 ID 需要保持一致~

在服务管理中,发现 order-service 服务出现在了 dev 环境中~

但此时 product-service 服务还是在 public 环境中的,此时访问接口会出现失败~

报错信息如下:没有 product-service 实例

修改 product-service 的其中一个实例,命名空间改为 dev:
修改完毕后,重启一个 product-service 服务
此时再进行接口测试,可以获取数据~~
Nacos 配置中心
除了注册中心和负载均衡之外,Nacos 还是一个配置中心,具有配置管理的能力。
Namespace 的常用场景之一是不同环境的配置区分配置隔离。例如将 dev 环境 prod 环境的配置进行隔离。
由 Nacos 的配置中心统一对多个服务的,多种环境的配置进行统一管理。通过配置中心,可以集中查看,修改,删除配置,无需再逐个修改配置文件。

1. 服务启动时,从配置中心读取配置项的内容,进行初始化。
2. 配置项修改的时候,通知微服务,实现配置的重新加载。
添加配置
在 Nacos 控制台添加配置项

注意:配置管理的命名空间和服务列表的命名空间,两者是隔离的,是分别设置的。默认都是 public。 服务管理命名空间配置 ≠ 配置管理的命名空间。

-
Data ID 设置为项目名称
-
配置内容的数据格式,目前只支持 properties 和 yaml 类型
获取配置
- 在 product-service 种引入 Nacos Config 依赖

配置 bootstrap.yml
微服务启动之前,需要先获取 nacos 中配置,并于 application.yml 配置合并。在微服务运行之前,Nacos 要求必须使用 bootstrap 配置文件来配置 nacos Server 的地址

spring.application.name 需要和 nacos 配置管理的 Data ID 保持一致
spring.cloud.nacos.config.server-addr 为 Nacos Server 的地址
注意:
配置中心和服务中心的配置是隔离的
Nacos 配置中心是:spring.cloud.nacos.config.server-addr
Nacos 服务中心是:spring.clooud.nacos.discovery.server-addr

测试:
重启服务,访问接口:127.0.0.1:9090/config/get

在 Nacos 配置中心的控制台修改 nacos.test.num

再次访问接口:

常见问题
- 读不到配置项
可能原因:配置信息错误:Data ID,配置格式,配置空间等
未引入依赖
- No spring.config.import.property has been defined

SpringCloud 2020.* 之后的版本将 bootstrap 禁用了,导致在读取文件的时候读取不到而报错,将 bootstrap 包重新导入即可
配置中心详解
设置命名空间
Nacos 配置管理的命名空间和服务列表的命名空间是分别设置的。默认是 public。
Nacos 配置管理的命名空间依然在 bootstrap 文件中进行配置


设置命名空间后,在配置管理可以设置对应的配置,项目启动时候,会从命名空间下找到响应的配置项。


Data Id
Data Id 格式介绍:
Nacos Spring Cloud 中,DataId 完整格式如下:

prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config,prefix 来进行配置
spring.profiles.active 即为当前环境对应的 profile,当 sroring.profiles.active 为空对应的 "-" 连接符也不存在。
file.extension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config,file-extension 来配置。目前只支持 properties 和 yaml 类型,默认为 properties。


添加配置项后重启服务,观察日志:

在 Nacos 中进行如下配置项:


注意:
-
bootstrap 中设置的配置格式必须和 nacos 控制台配置的数据格式保持一致
-
不设置配置格式(spring.cloud.nacos.config.file-extension)时,默认为 properties。
服务部署
修改数据库,Nacos 等相关配置
在加载配置文件中,会先对 bootstrap 文件进行加载,再对 application 文件进行加载。
所以一些重复的配置文件可以进行删除
在 application 中的 spring.application.name 配置就可以删除,只在 bootstrap 中存在即可。
并且,在有了 application-dev 和 application-prod 之后,application 的作用只是 spring.profies.active 中进行打包选择,这个配置在 bootstrap 中也存在,所以可以直接将 application 删除~~



再在 pom 文件中添加如下配置

当我们添加完上述配置后,利用 maven 的 package 进行打包时,可以正常完成打包,但是当选择 dev 进行本地运行测试的时候,出现报错:

无法解析这个 @profile.name@
解决办法:
在 pom 文件中设置一段资源定位

这样在本地就可以正常选择 dev 运行了
order-service 中
现在 pom 中添加配置:

再因为没有 bootstrap 文件,就正常像以前一样分出 dev 和 prod 即可



可以在 Linux 服务器上再创建一个文件夹来存放这个 nacos 的代码
然后将两个 jar 包直接拉到 Linux 服务器对应的文件中
启动 Nacos,启动前最好先把 data 数据删除掉~~
启动后,还可以查询一下以前 eureka 的 java 服务是否仍然启动着,如果仍然启动着,端口号被占用,可以将进程杀死~~
启动服务:

观察 Nacos 控制台

测试接口: IP:8080/order/1
返回结果正常~~
Nacos 和 Eureka 的区别
共同点
都支持服务注册和服务拉取
区别
- 功能
Nacos 除了服务发现和服务注册之外,还提供了配置中心,流量管理和 DNS 服务等功能
- CAP 理论
Eureka 遵循 AP 原理,Nacos 可以切换 AP 和 CP 模式。默认是 AP 原理。
Nacos 根据配置识别 CP 或者 AP 模式,如果注册 Nacos 的 Client 的节点是临时节点,那么 Nacos 对这个 Client 节点的效果就是 AP,反之是 CP。AP 和 CP 可以同时存在。
- 服务发现
Eureka:**基于拉模式。**Eureka Client 会定期从 Server 拉取服务信息,有缓存,默认每 30 秒拉取一次。
Nacos:基于推送模式,服务列表有变化时,会实时推送给订阅者,服务端和客户端保持心跳连接。
可以通过日志来观察:
启动 order-service 和 product-service 后,进行一次查询,观察 order-service 日志

**Receive server push request:**表示 Nacos客户端接收到了 Nacos 服务器推送的服务实例变更通知。
**Ack server push request:**表示 Nacos 客户端已确认收到该推送通知,并向服务器返回了已经确认收到该推送通知。
当将 product-sevice 服务停止:
在 order-service 服务会有如下日志
