Spring Cloud Nacos 服务注册与配置中心实战
0. 前言
本文基于以下技术栈进行讲解:
- SpringBoot:
3.2.5 - SpringCloud:
2023.0.3 - SpringCloud Alibaba:
2023.0.1.0 - Nacos:
2.2.3
1. 概述
Nacos (Dynamic Naming and Configuration Service) 是阿里巴巴开源的动态服务发现、配置管理和服务管理平台。在 Spring Cloud 体系中,它主要承担两大核心职责:服务注册与发现以及动态配置管理。
启动与基础配置
下载 Nacos 后,双击 startup.cmd 即可启动,默认端口为 8848。如果是单机模式开发,需修改配置文件中的集群模式:
set MODE="standalone"
访问控制台地址 http://127.0.0.1:8848/nacos/ 即可看到管理界面。
2. 服务注册与发现
微服务架构中,服务提供者(Provider)启动时将自身信息(IP、端口、服务名)注册到 Nacos;服务消费者(Consumer)通过查询 Nacos 获取可用实例列表,并依据负载均衡策略调用。
引入依赖
在需要注册服务的模块中添加以下依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置连接
在 application.yml 中指定 Nacos 服务器地址:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
启动服务后,登录 Nacos 控制台查看'服务管理',确认服务是否已注册成功。
3. 远程调用
3.1 RestTemplate 基础用法
RestTemplate 是 Spring 提供的同步 HTTP 客户端。假设我们有 order-service 和 product-service 两个微服务,订单服务需要调用商品服务获取详情。
直接硬编码 IP 的方式存在痛点:一旦服务 IP 变更或环境切换,代码必须修改。因此我们推荐使用服务名调用。
首先配置 RestTemplate Bean:
@Configuration
public class BeanConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
业务层调用示例:
@Service
public class OrderService {
private final OrderMapper orderMapper;
private final RestTemplate restTemplate;
@Autowired
public OrderService(OrderMapper orderMapper, RestTemplate restTemplate) {
this.orderMapper = orderMapper;
this.restTemplate = restTemplate;
}
public OrderInfo selectOrderById(Integer id) {
OrderInfo orderInfo = orderMapper.selectOrderById(id);
// 硬编码 IP 方式,不推荐在生产使用
String url = "http://127.0.0.1:9000/product/getProductById?id=" + orderInfo.getProductId();
ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
orderInfo.setProductInfo(productInfo);
return orderInfo;
}
}
3.2 结合 Nacos 实现服务发现调用
要利用 Nacos 的服务发现能力,只需将 @LoadBalanced 注解添加到 RestTemplate Bean 上,并将 URL 中的 IP 替换为服务名。
@Configuration
public class BeanConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
调用时直接使用服务名:
String url = "http://product-service/product/getProductById?id=" + orderInfo.getProductId();
ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
此时 Nacos 会自动解析 product-service 对应的实际 IP 地址。
4. 负载均衡
Nacos 本身负责注册,负载均衡主要由客户端(如 Spring Cloud LoadBalancer)完成。默认策略(轮询、随机)可能不会读取 Nacos 实例的权重属性。
若要让 Nacos 配置的权重生效,需在消费者端开启 Nacos 负载均衡策略:
spring:
cloud:
loadbalancer:
nacos:
enabled: true
在 Nacos 控制台的'服务列表'中编辑实例,可以设置不同实例的权重值,流量将按权重分配。
5. 同集群优先访问
当服务部署在不同区域(如北京、上海)时,为了降低延迟,应优先调用同集群实例。
服务提供者配置(启动参数):
-Dspring.cloud.nacos.discovery.cluster-name=cluster-beijing
服务消费者配置(yml):
spring:
cloud:
nacos:
discovery:
cluster-name: cluster-beijing
6. 健康检查
Nacos 支持两种健康检查机制,确保调用指向健康实例:
- 客户端主动上报:心跳间隔 5 秒,超过 15 秒未收到心跳标记为不健康,30 秒删除。适用于临时实例(默认类型)。
- 服务器端反向探测:Nacos 主动探知,间隔 20 秒。适用于非临时实例。
如需将服务注册为非临时实例(持久化),可在配置中添加:
spring:
cloud:
nacos:
discovery:
ephemeral: false
注意:实例类型确定后不可随意更改,否则可能导致启动报错。若需修改,建议停止 Nacos 服务并清理 /data/protocol/raft 目录下的元数据文件后重启。
7. 环境隔离
多环境(开发、测试、生产)之间需要严格隔离,避免相互干扰。Nacos 通过 Namespace(命名空间)实现这一功能。
- 在 Nacos 控制台创建新的命名空间。
- 在应用配置中指定 namespace ID:
spring:
cloud:
nacos:
discovery:
namespace: 0bec5adc-2787-44b0-b826-e4bb48746c4e
不同命名空间下的服务互不可见,实现了物理或逻辑上的隔离。
8. 配置中心
传统配置文件修改需重启应用,且难以维护多环境配置。Nacos 配置中心支持集中管理和实时生效。
引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
Bootstrap 引导文件
从 Spring Cloud 2020.0.0 版本起,默认禁用了 bootstrap 上下文。若需使用 Nacos 配置中心,需显式引入 bootstrap 依赖并配置 bootstrap.yml。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
bootstrap.yml 优先级高于 application.yml,用于加载配置中心地址等信息:
spring:
application:
name: order-service
profiles:
active: local
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: 0bec5adc-2787-44b0-b826-e4bb48746c4e
file-extension: yaml
discovery:
server-addr: 127.0.0.1:8848
ephemeral: true
namespace: 0bec5adc-2787-44b0-b826-e4bb48746c4e
Data ID 与优先级
Nacos 根据规则构建 Data ID 来查找配置文件:
Data ID = ${prefix} - ${spring.profiles.active} . ${file-extension}
以 order-service 为例,会同时监听以下三个配置:
order-service-local.yaml(优先级最高)order-service.yamlorder-service
配合 @RefreshScope 注解,配置变更后无需重启即可生效。
配置优先级验证
可以通过 Controller 测试配置值的读取优先级:
@RestController
@RequestMapping("/config")
@RefreshScope
@Slf4j
public class NacosConfigController {
@Value("${test.value}")
private String value;
@GetMapping("/getValue")
public void getValue() {
log.info("getValue:{}", value);
}
}
访问接口观察日志输出,删除低优先级配置文件后再次访问,可验证高优先级配置覆盖低优先级配置的结论。


