Nacos — 服务发现与配置中心
架构概览
Nacos(Naming and Configuration Service)是阿里巴巴开源的服务发现与配置管理平台,一站式解决微服务的注册发现和配置管理需求。
┌─────────────────────────────────────────────────────┐
│ Nacos Server │
│ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ 服务注册发现 │ │ 配置管理 │ │
│ │ (AP/CP可切换)│ │ (命名空间/Group/DataId) │ │
│ └──────────────┘ └──────────────────────────┘ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 一致性协议层 │ │
│ │ AP: Distro(自研,类 Gossip) │ │
│ │ CP: Raft(JRaft 实现) │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘AP vs CP 模式
| 模式 | 协议 | 适用场景 |
|---|---|---|
| AP(默认) | Distro | 服务注册发现,允许短暂不一致,优先可用性 |
| CP | Raft | 配置管理、需要强一致性的服务注册 |
bash
# 注册服务时指定 ephemeral=false 使用 CP 模式
# ephemeral=true(默认)→ AP 模式,临时实例
# ephemeral=false → CP 模式,持久化实例服务注册与发现
Spring Cloud 集成
xml
<!-- pom.xml -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2023.0.1.0</version>
</dependency>yaml
# application.yml
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: dev # 命名空间隔离
group: DEFAULT_GROUP
cluster-name: BJ # 集群名,就近访问
metadata:
version: v1.2.0
env: production健康检查机制
临时实例(ephemeral=true):
客户端心跳 → Nacos Server(默认 5s 一次)
15s 未收到心跳 → 标记为不健康
30s 未收到心跳 → 删除实例
持久化实例(ephemeral=false):
Nacos Server 主动探测(HTTP/TCP/MySQL)
探测失败 → 标记为不健康,但不删除服务发现与负载均衡
java
// 使用 LoadBalancerClient
@Autowired
private LoadBalancerClient loadBalancer;
public String callOrderService() {
ServiceInstance instance = loadBalancer.choose("order-service");
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/api/orders";
return restTemplate.getForObject(url, String.class);
}
// 使用 @LoadBalanced RestTemplate(推荐)
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 直接使用服务名
restTemplate.getForObject("http://order-service/api/orders", String.class);配置管理
配置模型
Namespace(命名空间)→ 环境隔离(dev/test/prod)
└── Group(分组)→ 应用分组
└── DataId(配置 ID)→ 具体配置文件
格式:${spring.application.name}-${spring.profiles.active}.${file-extension}
示例:order-service-prod.yamlSpring Cloud Config 集成
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>yaml
# bootstrap.yml(必须用 bootstrap,优先于 application)
spring:
application:
name: order-service
profiles:
active: prod
cloud:
nacos:
config:
server-addr: localhost:8848
namespace: prod-namespace-id
group: ORDER_GROUP
file-extension: yaml
# 共享配置(多服务共用)
shared-configs:
- data-id: common-db.yaml
group: COMMON_GROUP
refresh: true
# 扩展配置(优先级高于 shared-configs)
extension-configs:
- data-id: order-service-extra.yaml
group: ORDER_GROUP
refresh: true配置热更新
java
@RestController
@RefreshScope // 标注此注解,配置变更时自动刷新
public class OrderController {
@Value("${order.timeout:5000}")
private int timeout;
@Value("${order.max-retry:3}")
private int maxRetry;
}
// 或使用 @ConfigurationProperties(推荐,类型安全)
@Component
@ConfigurationProperties(prefix = "order")
@RefreshScope
@Data
public class OrderProperties {
private int timeout = 5000;
private int maxRetry = 3;
private String paymentUrl;
}监听配置变更
java
@Autowired
private NacosConfigManager configManager;
@PostConstruct
public void listenConfig() throws NacosException {
configManager.getConfigService().addListener(
"order-service-prod.yaml",
"ORDER_GROUP",
new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
log.info("Config changed: {}", configInfo);
// 手动处理配置变更逻辑
}
@Override
public Executor getExecutor() {
return null; // null 表示使用默认线程池
}
}
);
}集群部署
集群模式配置
bash
# cluster.conf(所有节点相同)
192.168.1.10:8848
192.168.1.11:8848
192.168.1.12:8848properties
# application.properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://mysql:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user.0=nacos
db.password.0=nacos_password数据持久化
Nacos 集群必须配置外部 MySQL 存储配置数据(服务注册数据存内存+磁盘):
sql
-- 初始化 Nacos 数据库
source /nacos/conf/mysql-schema.sql;命名空间隔离最佳实践
推荐方案:按环境隔离
├── dev(开发环境)
├── test(测试环境)
├── staging(预发布)
└── prod(生产环境)
不推荐:按服务隔离(命名空间过多,管理复杂)故障处理案例
案例一:服务注册后无法被发现
排查步骤:
bash
# 1. 检查服务是否注册成功
curl "http://nacos:8848/nacos/v1/ns/instance/list?serviceName=order-service&namespaceId=dev"
# 2. 检查健康状态
curl "http://nacos:8848/nacos/v1/ns/instance?serviceName=order-service&ip=192.168.1.100&port=8080"
# 3. 检查命名空间和 Group 是否匹配常见原因:
- 消费者和提供者的
namespace/group不一致 - 服务名大小写不匹配
- 网络隔离导致心跳无法到达
案例二:配置不生效
排查:
bash
# 检查配置是否发布
curl "http://nacos:8848/nacos/v1/cs/configs?dataId=order-service-prod.yaml&group=ORDER_GROUP&tenant=prod-ns-id"
# 检查客户端是否收到推送(查看日志)
grep "config changed" application.log常见原因:
@RefreshScope未添加bootstrap.yml中 namespace 填写的是名称而非 ID- 配置文件扩展名不匹配(
file-extension: yaml但 DataId 是.properties)
案例三:Nacos 集群脑裂
现象:网络分区后,各节点数据不一致。
处理:
bash
# 查看集群状态
curl http://nacos:8848/nacos/v1/core/cluster/nodes
# 查看 Raft 状态(CP 模式)
curl http://nacos:8848/nacos/v1/core/cluster/raft/leaderNacos 集群建议部署奇数节点(3或5),并确保节点间网络稳定。
监控指标
bash
# Nacos 暴露 Prometheus 指标
curl http://nacos:8848/nacos/actuator/prometheus| 指标 | 说明 |
|---|---|
nacos_monitor_service_count | 注册服务数 |
nacos_monitor_instance_count | 注册实例数 |
nacos_monitor_config_count | 配置数量 |
nacos_monitor_notify_task_count | 配置推送任务数 |