Nacos 使用指南
Nacos 是阿里巴巴开源的服务注册、发现和配置管理平台。
一、服务注册与发现
Dubbo 集成(推荐)
Dubbo 原生集成 Nacos 作为注册中心,使用 @EnableDubbo 即可同时启用服务注册与发现。
Maven 依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency>版本由
dubbo-dependencies-bom统一管理,推荐 3.3.6。
application.yml(Provider)
spring:
application:
name: user-service
dubbo:
application:
name: ${spring.application.name}
protocol:
name: dubbo # dubbo / tri(gRPC 兼容)
port: 20880 # -1 = 自动分配端口
registry:
address: nacos://127.0.0.1:8848
parameters:
namespace: dev # Nacos 命名空间 ID
group: DEFAULT_GROUP定义服务接口(公共 api 模块)
// 放在独立的 api 模块中,Provider 和 Consumer 共同依赖
public interface UserService {
UserDTO getById(Long id);
Result<Long> create(UserCreateCmd cmd);
List<UserDTO> listByCondition(UserQuery query);
}Provider(提供者)
@DubboService
public class UserServiceImpl implements UserService {
@Override
public UserDTO getById(Long id) {
return userMapper.selectById(id);
}
@Override
public Result<Long> create(UserCreateCmd cmd) {
// 业务逻辑
return Result.success(userId);
}
}
// 启动类
@EnableDubbo
@SpringBootApplication
public class UserServiceApplication { }Consumer(消费者)
@RestController
public class OrderController {
@DubboReference
private UserService userService;
@PostMapping("/orders")
public Result<Long> createOrder(@RequestBody OrderCmd cmd) {
UserDTO user = userService.getById(cmd.getUserId());
// 处理订单逻辑
return Result.success(orderId);
}
}
// 启动类
@EnableDubbo
@SpringBootApplication
public class OrderApplication { }@DubboService 参数
| 参数 | 说明 | 默认值 |
|---|---|---|
version | 服务版本号 | — |
group | 服务分组 | — |
timeout | 超时时间 ms | 1000 |
retries | 重试次数 | 2 |
loadbalance | 负载均衡策略 | random |
weight | 服务权重 | 100 |
cluster | 集群容错策略 | failover |
executes | 并发请求上限 | — |
delay | 延迟暴露 ms | 0 |
@DubboReference 参数
| 参数 | 说明 | 默认值 |
|---|---|---|
version | 目标服务版本 | — |
group | 目标服务分组 | — |
timeout | 超时时间 ms | 1000 |
retries | 重试次数 | 2 |
loadbalance | 负载均衡策略 | random |
cluster | 集群容错策略 | failover |
check | 启动时检查提供者 | true |
async | 异步调用 | false |
lazy | 延迟连接 | false |
injvm | 优先本地调用 | true |
负载均衡策略
| 策略 | 说明 |
|---|---|
random | 按权重随机(默认) |
roundrobin | 按权重轮询 |
leastactive | 最少活跃调用数 |
consistenthash | 一致性 Hash |
shortestresponse | 最短响应时间 |
集群容错策略
| 策略 | 说明 |
|---|---|
failover | 失败自动重试其他节点(默认) |
failfast | 快速失败,立即抛异常 |
failsafe | 忽略异常,记录日志 |
failback | 失败后后台定时重试 |
forking | 并行调用多节点取第一个成功 |
broadcast | 广播调用所有节点 |
版本与分组
// Provider 发布不同版本
@DubboService(version = "1.0.0", group = "stable")
public class UserServiceImplV1 implements UserService { }
@DubboService(version = "2.0.0", group = "beta")
public class UserServiceImplV2 implements UserService { }
// Consumer 指定版本
@DubboReference(version = "1.0.0", group = "stable")
private UserService userService;异步调用
@DubboReference(async = true)
private UserService userService;
public void process() {
userService.getById(1001L); // 立即返回
FutureAdapter<UserDTO> future = RpcContext.getServiceContext().getFuture();
// 执行其他操作...
UserDTO result = future.get(); // 阻塞获取结果
}二、配置中心
适用版本:Spring Boot 2.7.x + Spring Cloud 2021.0.x + Spring Cloud Alibaba 2021.0.x
Docker 部署 Nacos Server
单机模式(开发/测试环境)
docker run -d \
--name nacos \
-e MODE=standalone \
-e NACOS_AUTH_ENABLE=true \
-e NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789 \
-e NACOS_AUTH_IDENTITY_KEY=serverIdentity \
-e NACOS_AUTH_IDENTITY_VALUE=security \
-p 8848:8848 \
-p 9848:9848 \
nacos/nacos-server:v2.3.2端口说明
8848:HTTP 主端口(控制台 + 配置 API)9848:gRPC 端口(客户端长连接,必须暴露,否则配置推送和监听失效)9849:gRPC 集群通信端口(单机可不暴露)
常见坑点
从 Nacos 2.x 开始,客户端通过 gRPC(9848 端口)与服务端通信。如果 Docker 只映射了 8848 而没映射 9848,会导致:
- 配置获取超时
- 服务注册成功但配置拉不到
NacosException: Client not connected错误
Docker Compose 方式
# docker-compose.yml
version: '3.8'
services:
nacos:
image: nacos/nacos-server:v2.3.2
container_name: nacos
environment:
- MODE=standalone
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
- NACOS_AUTH_IDENTITY_KEY=serverIdentity
- NACOS_AUTH_IDENTITY_VALUE=security
- JVM_XMS=256m
- JVM_XMX=256m
- JVM_XMN=128m
ports:
- "8848:8848"
- "9848:9848"
volumes:
- nacos-logs:/home/nacos/logs
restart: unless-stopped
volumes:
nacos-logs:docker-compose up -d验证 Nacos 是否正常
# 访问控制台
open http://localhost:8848/nacos
# 默认账号密码:nacos / nacos
# API 验证
curl http://localhost:8848/nacos/v1/console/health/readiness版本对应关系
Spring Boot 2.7.x 对应的版本矩阵:
| 组件 | 版本 |
|---|---|
| Spring Boot | 2.7.x |
| Spring Cloud | 2021.0.x |
| Spring Cloud Alibaba | 2021.0.x |
| Nacos Server | 2.x(推荐 2.3.x) |
版本不匹配是配置获取失败的头号原因
Spring Cloud Alibaba 版本必须与 Spring Boot 版本匹配,否则自动配置类不会生效,配置静默拉取失败。
Maven 依赖(完整)
父 POM 依赖管理
<properties>
<spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.0.9</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.6.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
</dependencies>
</dependencyManagement>子模块依赖
<dependencies>
<!-- Nacos 配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- Bootstrap 上下文支持(Spring Boot 2.4+ 必须显式引入) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- Web(示例用) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>spring-cloud-starter-bootstrap 是关键
Spring Boot 2.4 之后默认不再加载 bootstrap.yml。如果不引入 spring-cloud-starter-bootstrap,bootstrap.yml 中的 Nacos 配置不会生效,导致应用启动时无法连接配置中心。
这是 Spring Boot 2.7.x 获取不到 Nacos 配置最常见的原因之一。
配置文件编写
方式一:bootstrap.yml(推荐,传统方式)
Spring Boot 2.7.x 下推荐使用此方式。
# src/main/resources/bootstrap.yml
spring:
application:
name: order-service
profiles:
active: dev
cloud:
nacos:
# Nacos 服务端地址
server-addr: 127.0.0.1:8848
# 认证信息(Nacos 开启鉴权时必须配置)
username: nacos
password: nacos
# ---- 配置中心 ----
config:
# 配置文件格式
file-extension: yaml
# 命名空间 ID(注意:是 ID,不是名称)
namespace: public
# 分组
group: DEFAULT_GROUP
# 是否开启配置刷新
refresh-enabled: true
# 共享配置(多个服务共用的配置)
shared-configs:
- data-id: common.yaml
group: DEFAULT_GROUP
refresh: true
# 扩展配置(优先级高于主配置)
extension-configs:
- data-id: db.yaml
group: DATABASE_GROUP
refresh: true# src/main/resources/bootstrap-dev.yml
spring:
cloud:
nacos:
config:
# dev 环境的命名空间 ID(从 Nacos 控制台复制)
namespace: e5a3b1c0-xxxx-xxxx-xxxx-xxxxxxxxxxxx方式二:application.yml(Spring Boot 2.4+ 新方式)
不依赖 bootstrap,直接在 application.yml 中使用 spring.config.import:
# src/main/resources/application.yml
spring:
application:
name: order-service
cloud:
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
config:
namespace: public
group: DEFAULT_GROUP
config:
import:
- nacos:order-service.yaml?refreshEnabled=true&group=DEFAULT_GROUP
- nacos:common.yaml?refreshEnabled=true&group=DEFAULT_GROUP两种方式的对比
| 特性 | bootstrap.yml | application.yml + import |
|---|---|---|
| 需要额外依赖 | 需要 spring-cloud-starter-bootstrap | 不需要 |
| 配置优先级 | 高于 application.yml | 等于 application.yml |
| 多 profile 支持 | 天然支持 bootstrap-dev.yml | 需要 import 中拼接 profile |
| Spring Boot 2.7.x 推荐 | 推荐 | 可用 |
| Spring Boot 3.x 推荐 | 不推荐 | 推荐 |
Nacos 控制台配置
创建配置
登录 Nacos 控制台 http://localhost:8848/nacos:
- 进入 配置管理 → 配置列表
- 选择对应的 命名空间(dev / test / prod)
- 点击 + 号创建配置
Data ID 命名规则:
${spring.application.name}-${spring.profiles.active}.${file-extension}例如 spring.application.name=order-service,spring.profiles.active=dev,file-extension=yaml:
| 配置项 | 值 |
|---|---|
| Data ID | order-service-dev.yaml |
| Group | DEFAULT_GROUP |
| 配置格式 | YAML |
配置内容示例:
# Nacos 控制台中的 order-service-dev.yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/order_db?useSSL=false&characterEncoding=utf8
username: root
password: your-password
driver-class-name: com.mysql.cj.jdbc.Driver
# 自定义配置
app:
name: 订单服务
version: 1.0.0
features:
- order-create
- order-query配置读取方式
@Value 注入
@RestController
@RefreshScope // 支持 Nacos 动态刷新
public class ConfigDemoController {
@Value("${app.name:默认应用名}")
private String appName;
@Value("${app.version:unknown}")
private String appVersion;
@GetMapping("/config")
public Map<String, String> getConfig() {
Map<String, String> map = new HashMap<>();
map.put("appName", appName);
map.put("appVersion", appVersion);
return map;
}
}@ConfigurationProperties 绑定
@Data
@Component
@ConfigurationProperties(prefix = "app")
@RefreshScope
public class AppProperties {
private String name;
private String version;
private List<String> features;
}@RestController
@RequiredArgsConstructor
public class AppConfigController {
private final AppProperties appProperties;
@GetMapping("/app-info")
public AppProperties getAppInfo() {
return appProperties;
}
}@NacosValue 注解(可选)
@RestController
public class NacosValueController {
@NacosValue(value = "${app.name:默认}", autoRefreshed = true)
private String appName;
@GetMapping("/nacos-value")
public String get() {
return appName;
}
}配置优先级(从高到低)
1. extension-configs(扩展配置,序号越大优先级越高)
2. shared-configs(共享配置,序号越大优先级越高)
3. ${spring.application.name}-${spring.profiles.active}.${file-extension}
4. ${spring.application.name}.${file-extension}
5. 本地 application.yml / application-dev.yml动态刷新(@RefreshScope)
在 Nacos 控制台修改配置并发布后,使用 @RefreshScope 标注的 Bean 会自动刷新:
@RefreshScope
@RestController
public class DynamicConfigController {
@Value("${app.greeting:Hello}")
private String greeting;
@GetMapping("/greeting")
public String get() {
return greeting + " " + LocalDateTime.now();
}
}验证动态刷新
- 修改 Nacos 中的
app.greeting值并发布 - 再次调用
/greeting接口 - 观察返回值是否变化
配置获取失败排查清单
以下是 Docker 部署 Nacos 后,Spring Boot 应用获取不到配置的常见原因和排查步骤:
1. 检查端口映射
# 确认 8848 和 9848 都已映射
docker port nacos
# 期望输出:
# 8848/tcp -> 0.0.0.0:8848
# 9848/tcp -> 0.0.0.0:9848如果缺少 9848 映射,配置推送和长连接监听全部失效。
2. 检查网络连通性
# 从应用所在机器访问 Nacos
curl http://127.0.0.1:8848/nacos/v1/console/health/readiness
# 检查 gRPC 端口
telnet 127.0.0.1 9848Docker 网络注意
如果应用也在 Docker 中运行,server-addr 不能写 127.0.0.1,需要使用 Docker 网络中的容器名或宿主机 IP:
spring:
cloud:
nacos:
server-addr: nacos:8848 # Docker Compose 中使用服务名3. 检查 namespace 是否为 ID
spring:
cloud:
nacos:
config:
# 错误:使用了命名空间名称
namespace: dev
# 正确:使用命名空间 ID(从 Nacos 控制台 → 命名空间 页面复制)
namespace: e5a3b1c0-xxxx-xxxx-xxxx-xxxxxxxxxxxxnamespace 必须用 ID
namespace 的值必须是 Nacos 控制台 命名空间 页面中显示的 命名空间 ID(UUID 格式),而不是命名空间名称。public 是唯一的例外,可以直接写 public 或留空。
4. 检查 Data ID 是否匹配
启动日志中查找实际请求的 Data ID:
# 启动日志中搜索这行
[fixed-DEFAULT_GROUP] data received, dataId=order-service-dev.yaml, group=DEFAULT_GROUP确保 Nacos 控制台中存在的 Data ID 与应用自动拼接的完全一致:
Data ID = ${spring.application.name}[-${spring.profiles.active}].${file-extension}| 场景 | Data ID |
|---|---|
| name=order-service, profile=dev, ext=yaml | order-service-dev.yaml |
| name=order-service, 无 profile, ext=yaml | order-service.yaml |
| name=order-service, profile=dev, ext=properties | order-service-dev.properties |
5. 检查鉴权配置
如果 Nacos 开启了鉴权(NACOS_AUTH_ENABLE=true),客户端必须配置用户名密码:
spring:
cloud:
nacos:
username: nacos
password: nacos鉴权不配置的表现
配置中心返回 403,但 Spring Boot 可能静默回退到本地配置,不报错,导致看起来"配置没拉到"。
6. 检查 bootstrap 是否生效
在 application.yml 或启动日志中确认:
# 如果看到以下日志,说明 bootstrap 已加载
Located property source: CompositePropertySource {name='NACOS', propertySources=[...]}如果完全看不到 Nacos 相关日志,说明 bootstrap.yml 没有被加载:
- 确认引入了
spring-cloud-starter-bootstrap依赖 - 确认配置文件名是
bootstrap.yml(不是bootstrap.yaml,两者都可以,但不要拼错)
7. 开启调试日志
# application.yml 或 bootstrap.yml 中添加
logging:
level:
com.alibaba.nacos: DEBUG
org.springframework.cloud.nacos: DEBUG通过日志可以看到完整的配置拉取过程、请求参数和响应结果。
完整可运行示例
项目结构
order-service/
├── pom.xml
└── src/main/
├── java/com/example/order/
│ ├── OrderApplication.java
│ └── controller/
│ └── ConfigController.java
└── resources/
├── bootstrap.yml
└── application.ymlpom.xml(关键部分)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<spring-cloud.version>2021.0.9</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.6.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>bootstrap.yml
spring:
application:
name: order-service
profiles:
active: dev
cloud:
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
config:
file-extension: yaml
namespace: public
group: DEFAULT_GROUPapplication.yml
server:
port: 8080
logging:
level:
com.alibaba.nacos: DEBUGOrderApplication.java
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}ConfigController.java
@RestController
@RefreshScope
public class ConfigController {
@Value("${app.name:未获取到配置}")
private String appName;
@GetMapping("/config/app-name")
public String getAppName() {
return appName;
}
}Nacos 控制台操作
- 创建配置:Data ID =
order-service-dev.yaml,Group =DEFAULT_GROUP - 配置内容:
app:
name: 订单服务-v1.0- 发布配置
- 启动应用,访问
http://localhost:8080/config/app-name - 期望返回:
订单服务-v1.0