Appearance
Nacos 教程
一、基础理论
1. 定位
- 注册中心:服务注册、服务发现、健康检查、负载均衡。
- 配置中心:集中化管理配置,支持动态刷新。
2. 核心架构
- Server:提供 OpenAPI,分 Naming(注册)和 Config(配置)模块。
- Client:嵌入式 SDK,与 Server 保持连接获取服务列表和配置。
- 2.x 核心变化:使用 gRPC 长连接 替代 1.x 的 HTTP 短连接 + 定时心跳。
3. 注册中心原理
- 服务启动通过 HTTP/gRPC 向 Nacos Server 注册实例。
- 1.x:Client 每 5s 发 HTTP 心跳;Server 15s 标记不健康,30s 剔除。
- 2.x:基于 gRPC 长连接的心跳检测,连接断开即感知。
- 消费者通过 本地缓存 + 订阅推送 方式获取实例列表,避免单点压力。
本地缓存 + 订阅推送拆解:
- 消费者启动时从 Nacos Server 拉取全量提供者列表,缓存到 本地 JVM 内存(并落盘快照)。
- 每次调用直接从本地内存取 IP:Port,不经过 Server,调用速度纳秒级。
- 当提供者上下线时,Server 主动推送变更给消费者,消费者更新本地缓存。
- 好处:避免所有调用都查 Server 导致其成为流量瓶颈;Server 挂了也能靠本地缓存继续调用一段时间。
4. 配置中心原理
- Client 启动时拉取全量配置并缓存到本地快照。
- 通过 HTTP 长轮询(Long Polling) 监听变更:请求挂起 29.5s,期间配置变更立即返回;无变更则超时后重新发起。
- 变更后 Client 发布
RefreshEvent,配合@RefreshScope刷新上下文。
5. 一致性协议
- 注册中心:默认 AP(Distro 协议,阿里自研),优先保证可用性;支持切换 CP(Raft)。
- 配置中心:默认 CP(使用 JRaft 保证配置一致性)。
6. 经典对比
| 维度 | Eureka | Consul | Nacos |
|---|---|---|---|
| CAP | AP | CP | AP/CP 切换 |
| 协议 | HTTP | HTTP/DNS | HTTP/gRPC |
| 健康检查 | Client 心跳 | TCP/HTTP/GRPC | Client 心跳/服务端探测 |
| 多语言 | Java 友好 | 全语言 | Java/Go/Python 等 |
| SpringCloud | 原生支持 | 集成需依赖 | Alibaba 官方支持 |
二、工作实践(复制即用)
1. 单机安装
bash
# 下载解压后启动
sh startup.sh -m standalone
# 控制台
http://localhost:8848/nacos
# 账号/密码:nacos/nacos
# ⚠️ 2.x 必须暴露端口:8848(HTTP) + 9848(gRPC)bash
docker run --name nacos \
-e MODE=standalone \
-p 8848:8848 \
-p 9848:9848 \
-d nacos/nacos-server:v2.3.02. 服务注册中心(Provider)
pom.xml
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>application.yml
yaml
server:
port: 8081
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: public
group: DEFAULT_GROUP启动类
java
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}3. 服务消费与调用(Consumer + OpenFeign)
pom.xml
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-starter-openfeign</artifactId>
</dependency>
<!-- 负载均衡器(Spring Cloud 2020+ 替代 Ribbon) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>Feign 接口
java
@FeignClient(name = "order-service")
public interface OrderClient {
@GetMapping("/order/{id}")
String getOrder(@PathVariable("id") Long id);
}调用方代码
java
@RestController
public class UserController {
@Autowired
private OrderClient orderClient;
@GetMapping("/user/order/{id}")
public String getOrder(@PathVariable Long id) {
return orderClient.getOrder(id);
}
}调用方启动类
java
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}4. 配置中心
pom.xml
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>application.yml(Spring Cloud Alibaba 2021+ 推荐写法)
yaml
server:
port: 8081
spring:
application:
name: order-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
config:
import:
- nacos:order-service.yaml?group=DEFAULT_GROUP&refreshEnabled=trueNacos 控制台新建配置
| 字段 | 值 |
|---|---|
| Data ID | order-service.yaml |
| Group | DEFAULT_GROUP |
| 配置格式 | YAML |
| 配置内容 | my:name: nacos-config |
代码读取(支持热更新)
java
@RestController
@RefreshScope
public class ConfigController {
@Value("${my.name:default}")
private String name;
@GetMapping("/name")
public String name() {
return name;
}
}三、核心速查表
| 配置项 | 说明 |
|---|---|
server-addr | Nacos 地址,集群用逗号分隔 |
namespace | 命名空间 ID,用于环境隔离 |
group | 配置/服务分组,默认 DEFAULT_GROUP |
file-extension | 配置格式:yaml / properties |
spring.config.import | 导入 Nacos 配置的入口(2.7+ 必须显式声明) |
@RefreshScope | 作用在 Bean 上,实现配置热刷新 |
9848 | Nacos 2.x 必须暴露的 gRPC 端口 |
四、排错速查
| 现象 | 解决 |
|---|---|
| 服务注册不上 | 检查 9848 端口是否开放;检查 server-addr 是否正确 |
Feign 调用 503 / no available server | 1. 确认提供者已注册 2. 消费者是否引入 spring-cloud-starter-loadbalancer |
| 配置不刷新 | 检查 @RefreshScope;检查 spring.config.import 是否加了 refreshEnabled=true |