


专栏:Spring Cloud
个人主页:手握风云
目录
[一、Nacos 简介](#一、Nacos 简介)
[1.1. 背景](#1.1. 背景)
[1.2. 起源](#1.2. 起源)
[1.3. 生态与业务](#1.3. 生态与业务)
[二、Nacos 安装](#二、Nacos 安装)
[2.1. 获取安装包](#2.1. 获取安装包)
[2.2. Windows 单机部署](#2.2. Windows 单机部署)
[2.3. Linux 单机部署](#2.3. Linux 单机部署)
[3.1. 引入依赖](#3.1. 引入依赖)
[3.2. 配置服务注册](#3.2. 配置服务注册)
[3.3. 实现远程调用](#3.3. 实现远程调用)
[四、Nacos 负载均衡精细化](#四、Nacos 负载均衡精细化)
[4.1. 手动上下线实例](#4.1. 手动上下线实例)
[4.2. 权重负载均衡](#4.2. 权重负载均衡)
[4.3. 同集群优先访问](#4.3. 同集群优先访问)
一、Nacos 简介
1.1. 背景
2018 年微服务注册中心领域发生了一次关键变动,当年 6 月 Eureka 官方宣布 2.0 版本闭源停止迭代,仅保留 1.X 版本进行基础维护。同年 7 月,阿里巴巴正式开源 Nacos 项目,凭借一站式微服务治理能力迅速在国内开发者群体中走红,成为替代 Eureka 的主流方案。从开源热度来看,Nacos 的 Github Star 数量早已突破 28K,而同期 Eureka 仅有 12K,足以体现国内技术生态对 Nacos 的认可与选择。
1.2. 起源
Nacos 并非从零开发的全新组件,而是阿里将内部三套独立服务整合后统一对外开源的产物,三套组件分别承担不同能力:Configserver 作为非持久化注册中心、VIPServer 提供持久化注册能力、Diamond 专门负责配置管理。整合之后的 Nacos 跳出了单一注册中心的局限,形成一体化产品形态,全称是 Dynamic Naming and Configuration Service,官方定位为面向云原生应用的动态服务发现、配置管理、服务管理综合平台,兼具注册中心与配置中心双重核心能力。
1.3. 生态与业务
在开发语言适配层面,Nacos 具备极强的通用性,几乎覆盖当前行业所有主流编程语言,能够适配不同技术栈的微服务项目。其中包含 Java、Go、C++、Nodejs、Python、Scala 等,无论后端服务采用何种语言开发,都可以快速接入 Nacos 完成服务注册、配置拉取等操作,降低了多技术栈架构下统一治理的成本。
Nacos 对外提供三大核心功能模块,覆盖微服务治理两大核心场景。第一是服务发现与管理,承担传统注册中心的全部职责,完成服务注册、实例健康感知、流量分发;第二是动态 DNS 服务,支持基于域名的服务寻址,适配云原生网络调度需求;第三是动态配置服务,集中统一管理所有微服务的配置项,支持配置实时下发、热更新,无需重启服务即可生效。
- Nacos 官网:https://nacos.io/
- Github 仓库:https://github.com/alibaba/nacos
二、Nacos 安装
2.1. 获取安装包
Nacos 提供两种压缩格式安装包,分别是 .zip 与 .tar.gz,均可在 Github Releases 页面下载,对应下载地址为 Releases · alibaba/nacos · GitHub。
2.2. Windows 单机部署
下载压缩包后,必须解压至无中文、无空格的磁盘路径。解压完成后会生成多个核心文件夹,bin 目录存放 Windows、Linux 两端的启停脚本,conf 目录存放全部配置文件,target 目录内置 Nacos 运行所需 jar 包,同时附带 LICENSE、NOTICE 说明文件。其中 Windows 专用脚本为 startup.cmd 启动文件、shutdown.cmd 停止文件。


Nacos 默认配置为集群模式,直接启动会抛出网络异常,必须手动修改启动参数切换单机模式。使用记事本打开 bin 目录下 startup.cmd 文件,找到 set MODE="cluster" 代码,将 cluster 修改为 standalone,保存文件后才算完成模式切换。

修改完成后双击 startup.cmd 脚本启动服务,控制台会打印 Tomcat、Nacos 启动日志,出现 "Nacos started successfully in standalone mode" 代表启动成功。打开浏览器访问地址 http://127.0.0.1:8848/nacos,能正常打开 Nacos 后台管理页面即部署完成;服务运行后根目录会自动生成 logs 文件夹,所有运行、报错日志都保存在 logs/nacos.log 中。


2.3. Linux 单机部署
先将 nacos-server-2.2.3.zip 安装包上传至服务器 /usr/local/src 目录,执行解压命令 unzip nacos-server-2.2.3.zip,解压后的目录结构、文件夹作用和 Windows 完全一致。

进入 nacos/bin 目录执行启动脚本,bash startup.sh -m standalone。启动后可通过 logs/start.out 文件查看完整启动日志,服务成功启动后,通过 http://服务器IP:端口/nacos 访问管理后台。

三、快速上手
Nacos 完整适配 Spring Cloud Alibaba 生态,并且严格遵循 Spring Cloud 统一的服务注册、服务发现规范。从开发体验上看,接入 Nacos 和过去使用 Eureka 的整体逻辑十分接近,学习成本很低,但二者存在一处核心区别:Eureka 需要开发者单独新建工程、完整部署服务端,而 Nacos 自带可直接运行的服务端程序,只需启动服务端后,在业务微服务中引入对应依赖、填写连接配置就能完成接入。
Nacos discovery · alibaba/spring-cloud-alibaba Wiki · GitHub

3.1. 引入依赖
想要实现服务注册与服务发现,需要分两层引入项目依赖,先统一管控版本,再引入业务所需组件。首先要在父工程的 <dependencyManagement> 节点中导入 Spring Cloud Alibaba 的版本管理 pom,统一全局版本号。这里需要重点注意,Spring Boot、原生 Spring Cloud、Spring Cloud Alibaba 三者有严格的版本对应关系,版本错乱会直接触发各类启动异常,适配规则可以查看阿里云官方版本说明文档。
XML
<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>
版本锁定完成后,在 order-service、product-service 等业务微服务模块,分别引入两个核心依赖:spring-cloud-starter-alibaba-nacos-discovery 负责对接 Nacos 完成注册发现,spring-cloud-loadbalancer 提供客户端负载均衡能力,两个依赖缺一不可。
XML
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
3.2. 配置服务注册
依赖配置完毕后,需要在微服务的 yml 配置文件中填写 Nacos 服务连接地址,这是服务能够成功注册的前置条件。对应的配置键为 spring.cloud.nacos.discovery.server-addr,该配置无默认值,必须手动填写。本地开发场景填写 127.0.0.1:8848,服务器测试 / 生产环境则填写对应服务器 IP 与自定义端口。
XML
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
3.3. 实现远程调用
改造代码实现微服务间远程调用,改造分为两处核心内容。第一处是请求 URL 改造,抛弃硬编码 IP + 端口的传统写法,直接使用目标服务的 spring.application.name 服务名作为访问域名;第二处是对 RestTemplate 进行增强,新建配置类,在生成 RestTemplate 实例的 @Bean 方法上添加 @LoadBalanced 注解,开启客户端负载均衡,让框架自动根据服务名匹配所有可用服务实例。
java
package com.yang.order.service;
import com.yang.order.config.BeanConfig;
import com.yang.order.mapper.OrderMapper;
import com.yang.order.model.OrderInfo;
import com.yang.order.model.ProductInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public OrderInfo selectOrderById(Integer orderId) {
OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
String url = "http://product-service/product/" + orderInfo.getProductId();
ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
orderInfo.setProductInfo(productInfo);
return orderInfo;
}
}
代码改造完成后,即可启动多个微服务完成功能验证。先分别启动 order-service 和 product-service 两个服务,打开 Nacos 后台的服务管理页面,就能查看到两个服务成功注册的记录,此时访问 order 服务的测试接口,就能正常完成跨服务远程调用。如果想要直观验证负载均衡分发效果,可以修改启动端口,启动同一服务的多个实例,反复调用测试接口并打印日志,就能观察到请求会分发到不同实例上。

四、Nacos 负载均衡精细化
4.1. 手动上下线实例
控制台 - 服务详情 - 操作下线 / 上线,下线节点不再接收流量,适用于故障节点临时隔离。


4.2. 权重负载均衡
在实际生产环境中,不同服务器硬件性能会存在差异,我们可以借助 Nacos 的权重负载均衡能力,给性能更好的实例分配更多流量,以此充分利用服务器资源。权重的数值代表实例接收流量的占比,Nacos 控制台中每个服务实例的默认权重为 1,开发者可以直接在控制台编辑实例来修改权重大小。

仅仅修改控制台的权重数值还无法让配置生效。Spring Cloud LoadBalancer 组件本身自带一套负载均衡逻辑,默认并不会读取 Nacos 上设置的权重参数。因此需要在项目配置文件中手动开启 Nacos 专属的负载均衡策略,配置项如下,开启之后框架才会识别实例上配置的权重信息。
java
spring:
cloud:
loadbalancer:
nacos:
enabled: true
在修改权重编辑实例的时候,有可能会报出 Raft 找不到 Leader 节点的 500 异常。这个问题产生的原因是 Nacos 依靠 Raft 算法选举 Leader 节点,会保存之前的集群地址信息,当服务器 IP 发生变化之后,旧的记录就会失效,导致选主失败。对应的解决方式是关闭 Nacos 服务,删除 Nacos 根目录下 data 文件夹里面的 protocol 文件夹,清除旧的元数据缓存,重启之后就可以正常修改实例权重。

4.3. 同集群优先访问
Nacos 引入集群的概念,可以把部署在同一个机房内的服务实例划分到同一个集群当中,因此同集群优先访问,本质上就是同机房优先访问的能力。在真实的微服务项目中,同一个服务往往会部署大量实例,这些实例分布在不同机器,甚至跨多个机房。
举一个典型的业务场景,product‑service 服务一共存在三个实例,其中两个实例部署在上海机房,另外两个实例部署在北京机房。当服务进行远程调用的时候,业务上更希望优先访问本机房内部的实例。因为同一个机房内部属于局域网通信,网络延迟更低、稳定性更好。只有当本地机房的实例全部不可用之后,才去跨机房调用其他集群的实例。

想要实现该效果,首先需要为各个服务实例配置对应的集群名称。以 product‑service 为例,在 yaml 配置文件中通过如下配置指定集群标识,比如 SH 代表上海机房,BJ 代表北京机房。配置完成重启服务之后,就可以在 Nacos 控制台看到实例被归类到对应集群下。如果需要同一服务下不同实例归属不同集群,可以在启动项中添加 VM 选项,给不同端口的实例设置不一样的 cluster‑name 参数。作为调用方的 order‑service,同样需要配置和目标服务相同的集群名称。
java
spring:
cloud:
nacos:
discovery:
cluster-name: BJ


配置全部完成后就可以开展功能测试。正常情况下多次发起接口调用,日志可以看到请求只会分发到和调用方相同集群的实例。我们可以手动将本集群内所有实例执行下线操作,再次发起调用,这时就会自动降级,请求转发到其他集群的实例上,完成跨机房访问。