Ⅰ. Nacos简介
2018年6月,Eureka2.0 宣布闭源(但是1.X版本仍然为活跃项目),同年7月份,阿里 Nacos 宣布开源,并快速成为国内最受关注开源产品。作为 Eureka 的替代,Nacos 已经成为了国内开发者的首选,目前 Nacos Star 已经突破 28K(Eureka12K)

Nacos (Dynamic Na mingand Co nfiguration S ervice)
在最初开源时,Nacos 选择进行内部三个产品合并统一开源(Configserver 非持久注册中心、VIPServer 持久化注册中心、Diamond 配置中心)。定位为:一个更易于构建云原生应用的动态服务发现,配置管理和服务管理平台。所以 Nacos 是一个注册中心组件,但它又不仅仅是注册中心组件。
截至目前,Nacos 几乎支持了所有的主流语言,比如 Java、Go、C++、Nodejs、Python、Scala 等。
仓库:https://github.com/alibaba/nacos
Ⅱ. Nacos安装
下载地址:https://github.com/alibaba/nacos/releases
一、Windows
① 解压
把压缩包解压到任意非中文的目录下

-
bin:Nacos 启停脚本-
startup.cmd:windows 平台的启动脚本 -
shutdown.cmd:windows 平台的停止脚本 -
startup.sh:Linux 平台的启动脚本 -
shutdown.sh:Linux 平台的停止脚本
-
-
conf:Nacos 配置文件 -
target:存放 Nacos 应用的 jar 包
② 修改为单机模式
Nacos 默认启动方式为集群,启动前需要修改配置为单机模式。
-
使用记事本打开
startup.cmd -
Line26左右,修改启动模式:
set MODE="cluster" 改为: set MODE="standalone"
③ 启动Nacos
启动非常简单,进入bin目录下,双击 startup.cmd 即可。访问 Nacos 主页 http://127.0.0.1:8848/nacos,出现以下界面,表示 Nacos 启动成功。

二、Linux
同理下载好压缩包,然后上传到服务器上某个目录中。
然后进入 nacos/bin 目录,输入命令:
bash startup.sh -m standalone启动成功后,像之前那样访问网站即可。
Ⅲ. Nacos快速上手
Nacos 是 SpringCloudAlibaba 的组件,SpringCloudAlibaba 遵循 SpringCloud 中定义的服务注册,服务发现规范。因此使用 Nacos 和使用 Eureka 对于微服务来说,并没有太大区别。
主要差异在于:
-
Eureka 需要自己搭建一个服务,Nacos 不用自己搭建服务,组件已经准备好了,只需启动即可。
-
对应依赖和配置不同
操作参考:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery
一、服务注册/服务发现
① 引入Spring CloudAlibaba依赖
在父工程的 pom.xml 文件中的 <dependencyManagement> 中引入 SpringCloudAlibaba 依赖:
<properties>
<spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version>
</properties>
<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>💡 💡 注意:
SpringBoot和SpringCloud的版本是有一定对应关系的。SpringCloudAlibaba也遵循SpringCloud的标准,所以在引入依赖时一定要确认各个版本的对应关系。
SpringCloudAlibaba和SpringCloud版本对应关系,参考官方文档,版本在一定范围内可以自由选择。
② 引入Nacos依赖
在 order-service 和 product-service 中引入 Nacos 依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>③ 引入LoadBalance依赖
用 Nacos 时之所以要额外引入 spring-cloud-loadbalancer 依赖,是因为 Nacos 自己不提供客户端负载均衡能力。它只负责服务发现,不负责挑服务、轮询、权重策略这些 “选谁调用” 的逻辑。
因此在 Spring Boot 2.4+ 之后,必须引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>二、配置Nacos服务地址
spring:
application:
name: product-service
cloud:
nacos:
discovery:
server-addr: 49.235.136.223:8848 # 配置nacos服务访问地址三、远程调用
-
在
order-service中代码修改 IP 为项目名(同前面)public OrderInfo selectOrderById(Integer orderId) { OrderInfo orderInfo = orderMapper.selectOrderById(orderId); String url = "http://**product-service** /product/"+ orderInfo.getProductId(); *log*.info("product-service url: " + url); ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class); orderInfo.setProductInfo(productInfo); return orderInfo; } -
为 restTemplate 配置类添加负载均衡注解
@LoadBalanced@Configuration public class BeanConfig { @Bean **@LoadBalanced** public RestTemplate restTemplate(){ return new RestTemplate(); } }
四、启动服务
启动一个 order-service 服务,再启动三个 product-service 服务,观察 Nacos 的管理界面,发现 order-service 和 product-service 都注册在 Nacos 上了:

测试接口:http://127.0.0.1:8080/order/1
Ⅳ. Nacos负载均衡
生产环境相对是比较恶劣的,我们需要对服务的流量进行更加精细的控制。Nacos 支持多种负载均衡策略,包括权重、同机房、同地域、同环境等。
一、服务下线
当某一个节点上接口的性能较差时,我们可以第一时间对该节点进行下线。
操作步骤:服务详情 -> 下线

点击下线后,再次请求接口,会发现该服务没有请求进来了。再次单击上线,该节点会继续收到请求。
二、权重配置
除了下线之外也可以配置这个节点的流量权重
① 配置权重
操作步骤:找到对应节点 -> 编辑 -> 在弹出的窗口修改权重值

每个节点默认权重为 1,修改为 0.1。
② 开启Nacos负载均衡策略
由于 SpringCloudLoadBalance 组件自身有负载均衡配置方式,所以不支持 Nacos 的权重属性配置。
我们需要开启 Nacos 的负载均衡策略,让权重配置生效。
参考:如何解决MSENacos上修改服务实例的权重不生效问题_微服务引擎(MSE)-阿里云帮助中心
# 开启nacos的负载均衡策略
spring:
cloud:
loadbalancer:
nacos:
enabled: true③ 测试权重配置
启动服务,访问多次接口,观察结果,会发现 9091 端口号的实例接收的请求明显比另外两个实例少。
注意: 整体流量生效,局部流量不是严格按照设置的比例进行分配的。
三、同集群优先访问
Nacos 把同一个机房内的实例,划分为一个集群。所以同集群优先访问,在一定程度上也可以理解为同机房优先访问。
微服务架构中,一个服务通常有多个实例共同提供服务,这些实例可以部署在不同的机器上,这些机器可以分布在不同的机房,比如 product-service:
-
实例1:分布在上海机房
-
实例2:分布在上海机房
-
实例3:分布在北京机房
-
实例4:分布在北京机房

在微服务访问时,应尽量访问同机房的实例。当本机房内实例不可用时,才访问其他机房的实例 。
比如 order-service 在上海机房,product-service 在北京和上海机房都有实例,那我们希望可以优先访问上海机房。如果上海机房没有实例,或者实例不可用,再访问北京机房的实例。通常情况下,因为同一个机房的机器属于一个局域网,局域网访问速度更快一点。

① 给实例配置集群名称
- 为
product-service配置集群名称spring: cloud: nacos: discovery: server-addr: 49.235.136.223:8848 **cluster-name: SH** # 集群名称:上海集群 loadbalancer: nacos: enabled: true # 同样需要开启负载均衡策略
重启服务,观察 Nacos 控制台,SH 集群下多了一个实例

复制 product-service 启动配置,添加 VMOption,设置 9091 和 9092 端口实例的机房为 BJ:
-Dserver.port=9091 -Dspring.cloud.nacos.discovery.cluster-name=BJ
-Dserver.port=9092 -Dspring.cloud.nacos.discovery.cluster-name=BJ观察 Nacos,在 BJ 集群下多了两个实例

- 为
order-service配置集群名称spring: cloud: nacos: discovery: server-addr: 49.235.136.223:8848 **cluster-name: SH** # 集群名称: 上海集群 loadbalancer: nacos: enabled: true # 同样需要开启负载均衡策略

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

比如领导管理员工的工作
-
员工主动汇报:员工每天主动汇报自己工作进度
-
领导主动问询:领导每周向员工了解工作进度
Nacos 中的健康检查机制不能主动设置 ,健康检查机制是和 Nacos 的服务实例类型强相关的 ,所以下面来介绍一下服务实例类型都有哪些。
二、Nacos服务实例类型
Nacos 的服务实例(注册的节点)分为临时实例和非临时实例:
-
临时实例 :如果实例宕机超过一定时间,会从服务列表剔除,是 Nacos 的默认类型 。
-
非临时实例 :如果实例宕机,不会从服务列表剔除,也叫永久实例。
| 实例类型 | 设置 | 探活机制 | 由谁检测 | 无响应后的处理 |
|---|---|---|---|---|
| 临时实例 | ephemeral=true | 客户端主动上报机制(心跳) | 客户端主动上报 | 快速剔除 |
| 非临时实例 | ephemeral=false | 长连接检查 + 服务端反向探测 | Nacos 服务端 | 不主动剔除,等待失败探测 |
配置一个服务实例为永久实例:
spring:
cloud:
nacos:
discovery:
ephemeral: false # 设置为非临时实例重启服务,观察 Nacos 控制台。停止服务,再观察控制台,发现节点依然不会消失。

三、常见问题
① Nacos服务实例类型不允许改变
设置服务实例类型,重新启动 Nacos 可能会报错
报错信息参考:
Caused by: com.alibaba.nacos.api.exception.NacosException: failed to req
API:/nacos/v1/ns/instance after all servers([110.41.51.65:10020]) tried:
caused: errCode: 400, errMsg: Current service DEFAULT_GROUP@@product-service is
ephemeral service, can't register persistent instance. ;
at
com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy.reqApi(Naming
HttpClientProxy.java:410) ~[nacos-client-2.2.1.jar:na]
at
com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy.reqApi(Naming
HttpClientProxy.java:351) ~[nacos-client-2.2.1.jar:na]
at
com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy.reqApi(Naming
HttpClientProxy.java:346) ~[nacos-client-2.2.1.jar:na]
// ...原因:Nacos 会记录每个服务实例的 IP 和端口号,当发现 IP 和端口都没有发生变化时,Nacos 不允许一个服务实例类型发生变化,比如从临时实例变为非临时实例,或者从非临时实例变成临时实例。
解决办法:
-
停掉 nacos 服务
-
删除 nacos 目录中
/data/protocol/raft目录,里面保存了应用实例的元数据信息。 -
重启 nacos 服务
② 服务正常,Nacos健康检查失败
现象:服务正常,但是 Nacos 显示健康状态为 false。
原因和解决办法:如何解决Nacos持久化实例HTTP/TCP的健康检查不通过问题_微服务引擎(MSE)-阿里云帮助中心
Ⅵ. Nacos环境隔离
企业开发中,一个服务会分为开发环境,测试环境和生产环境。
-
开发环境: 开发人员用于开发的服务器,是最基础的环境。一般日志级别设置较低,可能会开启一些调试信息。
-
测试环境: 测试人员用来进行测试的服务器,是开发环境到生产环境的过渡环境。
-
生产环境: 正式提供对外服务的环境,通常关掉调试信息。
通常情况下,这几个环境是不能互相通信的。Nacos 提供了 namespace(命名空间)来实现环境的隔离 。不同的 namespace 的服务不可见。
一、创建Namespace
默认情况下,所有服务都在同一个 namespace,名为 public。

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

二、配置namespace
namespace 创建完成后,对服务进行配置:
| 配置项 | Key | 默认值 | 说明 |
|---|---|---|---|
| 命名空间 | spring.cloud.nacos.discovery.namespace |
无 |
常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 |
修改 order-service 的命名空间:
spring:
cloud:
nacos:
discovery:
namespace: 16cb6cdb-bc75-438b-a7a1-205b9a0afbd9 *# 命名空间ID*Ⅶ. Nacos配置中心
除了注册中心和负载均衡之外,Nacos 还是一个配置中心,具备配置管理的功能。
Namespace 的常用场景之一是不同环境的配置区分隔离。例如开发测试环境和生产环境的配置隔离。
一、为什么需要配置中心
当前项目的配置都在代码中,会存在以下问题:
-
配置文件修改时,服务需要重新部署。微服务架构中,一个服务可能有成百个实例,挨个部署比较麻烦,且容易出错。
-
多人开发时,配置文件可能需要经常修改,使用同一个配置文件容易冲突。
配置中心就是对这些配置项进行统一管理。通过配置中心,可以集中查看、修改和删除配置,无需再逐个修改配置文件 。提高效率的同时,也降低了出错的风险。

-
服务启动时,从配置中心读取配置项的内容,进行初始化。
-
配置项修改时,通知微服务,实现配置的更新加载。
二、快速上手
通过以下操作,我们先来感受下 Nacos 配置中心的使用。
参考文档:NacosSpringCloud快速开始Nacosconfig
① 添加配置
在 Nacos 控制台添加配置项:

💡 注意: 配置管理的命名空间和服务列表的命名空间是隔离的,两个是分开设置的,默认都是
public。简单的说就是,服务管理命名空间配置 ≠ 配置管理的命名空间
新建配置项:

配置内容:
nacos.config=public说明:
-
DataID 设置为项目名称
-
配置内容的数据格式
-
设置配置内容
② 获取配置
-
在
product-service中引入 NacosConfig 依赖:<!-- nacos配置中心依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- SpringCloud 2020.*之后版本需要引入bootstrap--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> -
在
product-service中创建bootstrap.properties配置文件:- 微服务启动前,需要先获取 nacos 中配置,并与
application.yml配置文件合并。在微服务运行之前,Nacos 要求必须使用bootstrap.properties配置文件来配置 NacosServer 地址 。
spring.application.name=product-service spring.cloud.nacos.config.server-addr=lirendada.art:8848- 或者创建
bootstrap.yml配置文件:
spring: application: name: product-service cloud: nacos: config: server-addr: lirendada.art:8848 - 微服务启动前,需要先获取 nacos 中配置,并与
💥注意事项:
-
spring.application.name需要和上面 nacos 配置管理中的 DataID 一致 -
spring.cloud.nacos.config.server-addr为 NacosServer 的地址
💡 配置中心和注册中心的配置是不同的、隔离的:
Nacos 配置中心:
spring.cloud.nacos.config.server-addrNacos 注册中心:
spring.cloud.nacos.discovery.server-addr
-
在
product-service中编写程序:import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; **@RefreshScope** @RestController public class NacosController { **@Value("${nacos.config}")** private String config; @RequestMapping("/getConfig") public String getConfig() { return "获取到nacos.config= " + config; } }-
@Value读取配置 -
@RefreshScope配置进行热更新
-
-
测试:
-
启动程序,访问接口:http://127.0.0.1:9090/getConfig
-
在 Nacos 控制台修改
nacos.config,再次访问接口
-
三、配置中心详解
① 设置命名空间
Nacos 配置管理的命名空间和服务列表的命名空间是分别设置的,默认是 public。
Nacos 命名空间配置依然在 bootstrap.properties 或者 bootstrap.yml 中进行配置:
spring:
application:
name: product-service
cloud:
nacos:
config:
server-addr: lirendada.art:8848
**namespace: 16cb6cdb-bc75-438b-a7a1-205b9a0afbd9** value 对应命名空间的ID,如下图所示:

② DataId
在 NacosSpringCloud 中,dataId 的完整格式如下所示:
${prefix}-${spring.profiles.active}.${file-extension}-
prefix:默认为spring.application.name的值,当然也可以通过配置项spring.cloud.nacos.config.prefix来配置。 -
spring.profiles.active:当前环境对应的 profile。当spring.profiles.active为空时,对应的连接符-也将不存在,dataId 的拼接格式变成${prefix}.${file-extension} -
file-exetension:配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension来配置。目前只支持properties和yaml类型,默认为properties。
微服务启动时,会从 Nacos 读取多个配置文件:
-
${prefix}-${spring.profiles.active}.${file-extension} -
${prefix}.${file-extension} -
${prefix}
💡
${spring.application.name}、${spring.profiles.active}等通过配置文件来指定时,必须放在bootstrap.properties配置文件中。
观察日志
在 bootstrap.yml 中添加 spring.profiles.active 值:
spring:
profiles:
active: dev启动服务,观察日志:

三个文件的读取优先级为:product-service-dev.properties > product-service.properties > product-service
💡注意:
-
bootstrap.yml设置的配置格式必须和 nacos 控制台配置的数据格式保持一致。 -
不设置配置格式(
spring.cloud.nacos.config.file-extension)时,该值默认为 properties。
Ⅷ. 服务部署
-
修改数据库,Nacos等相关配置
-
对两个服务进行打包
-
上传 jar 到 Linux 服务器
-
启动 Nacos(启动前最好把data数据删除掉)
-
启动服务
#后台启动order-service, 并设置输出日志到logs/order.log
nohup java -jar order-service.jar >logs/order.log &
#后台启动product-service, 并设置输出日志到logs/order.log
nohup java -jar product-service.jar >logs/product-9090.log &
#启动实例, 指定端口号为9091
nohup java -jar product-service.jar --server.port=9091 >logs/product-9091.log &- 测试
访问接口:http://lirendada.art:8080/order/1,观察远程调用的结果。
常见问题
① 如何多次在服务器关掉多个占用指定端口的程序
sudo lsof -t -i :8080 -i :9090 -i :9091 -i :9092 | xargs sudo kill -9② 在 bootstrap.yml 中配置了 profiles.active 之后无法识别到 @profile.name@ 的情况
在 pom.xml 文件中添加下面内容:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>