Spring Boot 集成 Nacos 完全指南:从配置中心到服务发现一站式实战
摘要:Nacos 作为阿里巴巴开源的一站式微服务管理平台,已成为 Spring Cloud Alibaba 生态的核心组件。本文基于 Spring Boot 3.x + Nacos 2.x 最新版本,系统讲解 Nacos 的安装部署、配置中心、服务发现等核心功能,并提供生产级最佳实践方案。
一、Nacos 核心认知
1.1 什么是 Nacos?
ini
┌─────────────────────────────────────────────────────────────┐
│ Nacos 核心定位 │
├─────────────────────────────────────────────────────────────┤
│ N = Naming 服务注册与发现 │
│ A = Configuration 配置管理 │
│ C = Service 微服务治理 │
│ O = O&M 运维监控 │
│ S = System 系统支撑 │
└─────────────────────────────────────────────────────────────┘
1.2 核心功能对比
| 功能模块 | 传统方案 | Nacos 方案 | 优势 |
|---|---|---|---|
| 服务注册 | Eureka | Nacos Naming | AP/CP 切换、健康检查 |
| 配置中心 | Config + Bus | Nacos Config | 实时推送、版本管理 |
| 服务发现 | Ribbon | Nacos Discovery | 权重路由、元数据 |
| 运维监控 | 分散工具 | Nacos Console | 统一控制台 |
1.3 版本兼容性矩阵
yaml
┌──────────────────────────────────────────────────────────────┐
│ Spring Boot 3.x 版本兼容表 │
├──────────────────────────────────────────────────────────────┤
│ Spring Boot │ Spring Cloud Alibaba │ Nacos Server │
├───────────────┼─────────────────────┼───────────────────────│
│ 3.3.x │ 2023.0.1.x │ 2.3.x - 2.4.x │
│ 3.2.x │ 2023.0.0.x │ 2.2.x - 2.3.x │
│ 3.1.x │ 2022.0.0.x │ 2.1.x - 2.2.x │
│ 3.0.x │ 2022.0.0.x │ 2.1.x - 2.2.x │
└──────────────────────────────────────────────────────────────┘
二、Nacos 服务器部署
2.1 下载与安装
方式一:官方下载
bash
# 访问 Nacos 官网下载
# https://github.com/alibaba/nacos/releases
# Linux/Mac 下载
wget https://github.com/alibaba/nacos/releases/download/v2.3.2/nacos-server-2.3.2.tar.gz
# 解压
tar -xzf nacos-server-2.3.2.tar.gz
cd nacos/bin
方式二:Docker 部署(推荐)
ini
# 单机模式
docker run -d \
--name nacos \
-e MODE=standalone \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=mysql-host \
-e MYSQL_SERVICE_DB_NAME=nacos_config \
-e MYSQL_SERVICE_USER=nacos \
-e MYSQL_SERVICE_PASSWORD=nacos \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
nacos/nacos-server:v2.3.2
# 查看日志
docker logs -f nacos
方式三:Docker Compose 部署
yaml
# docker-compose.yml
version: '3.8'
services:
nacos:
image: nacos/nacos-server:v2.3.2
container_name: nacos
environment:
- MODE=standalone
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
- MYSQL_SERVICE_PORT=3306
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
depends_on:
- mysql
restart: always
mysql:
image: mysql:8.0
container_name: nacos-mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: nacos_config
MYSQL_USER: nacos
MYSQL_PASSWORD: nacos123
ports:
- "3306:3306"
volumes:
- ./mysql-data:/var/lib/mysql
restart: always
2.2 启动命令
bash
# Windows 单机启动
startup.cmd -m standalone
# Linux 单机启动
sh startup.sh -m standalone
# Linux 集群启动
sh startup.sh
# 查看启动状态
tail -f logs/start.out
2.3 访问控制台
arduino
┌─────────────────────────────────────────┐
│ Nacos Console 访问信息 │
├─────────────────────────────────────────┤
│ 地址:http://localhost:8848/nacos │
│ 用户名:nacos │
│ 密码:nacos │
└─────────────────────────────────────────┘
三、Spring Boot 3 集成 Nacos 配置中心
3.1 项目依赖配置
Maven 配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>nacos-demo</artifactId>
<version>1.0.0</version>
<name>nacos-demo</name>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.1.2</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Nacos 配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${spring-cloud-alibaba.version}</version>
</dependency>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${spring-cloud-alibaba.version}</version>
</dependency>
<!-- Spring Boot Actuator(配置刷新必需) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Bootstrap 支持(Spring Boot 3 必需) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>4.1.3</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<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>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Gradle 配置
bash
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.5'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.example'
version = '1.0.0'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
ext {
set('springCloudVersion', "2023.0.3")
set('springCloudAlibabaVersion', "2023.0.1.2")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config'
implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery'
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
3.2 配置文件设置
bootstrap.yml(优先级最高)
yaml
# src/main/resources/bootstrap.yml
spring:
application:
name: user-service # 应用名称,用于生成 Data ID
cloud:
nacos:
config:
# Nacos 服务器地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yaml
# 命名空间 ID(留空使用 public)
namespace: your-namespace-id
# 配置分组
group: DEFAULT_GROUP
# 配置前缀(默认使用 spring.application.name)
prefix: ${spring.application.name}
# 共享配置
shared-configs:
- data-id: common-config.yaml
group: DEFAULT_GROUP
refresh: true
- data-id: database-config.yaml
group: DEFAULT_GROUP
refresh: true
# 扩展配置
extension-configs:
- data-id: redis-config.yaml
group: DEFAULT_GROUP
refresh: true
# 加密配置
encryption:
enabled: true
# 自定义加密器
encryptor: com.example.config.CustomEncryptor
# 长轮询超时时间
long-polling-timeout: 30000
# 配置拉取超时
config-long-poll-timeout: 30000
# 最大重试次数
max-retry: 5
# 重试间隔
retry-time: 2000
# 是否启用本地缓存
enable-remote-sync-config: true
# 本地缓存路径
config-cache-dir: ${user.home}/nacos/config
# 是否开启配置监听
enable-listener: true
# 用户名密码(Nacos 2.x 认证)
username: nacos
password: nacos
# 端点权限
context-path: /nacos
application.yml
yaml
# src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: user-service
profiles:
active: dev # 激活环境
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: your-namespace-id
group: DEFAULT_GROUP
# 服务实例元数据
metadata:
version: 1.0.0
region: cn-east
zone: zone-1
# 健康检查
health-check:
enabled: true
# 注册开关
register-enabled: true
# 心跳间隔
heart-beat-interval: 5000
# 心跳超时
heart-beat-timeout: 15000
# IP 删除超时
ip-delete-timeout: 30000
# 权重
weight: 1.0
# 是否启用
enabled: true
# Actuator 端点配置
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
health:
nacos:
enabled: true
# 日志配置
logging:
level:
com.alibaba.cloud.nacos: DEBUG
com.example: INFO
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n'
3.3 Nacos 控制台配置
创建配置文件
在 Nacos 控制台创建以下配置:
| Data ID | Group | 配置内容 |
|---|---|---|
| user-service.yaml | DEFAULT_GROUP | 应用专属配置 |
| user-service-dev.yaml | DEFAULT_GROUP | 开发环境配置 |
| common-config.yaml | DEFAULT_GROUP | 公共配置 |
| database-config.yaml | DEFAULT_GROUP | 数据库配置 |
| redis-config.yaml | DEFAULT_GROUP | Redis 配置 |
user-service.yaml 示例
yaml
# Nacos 配置中心 - user-service.yaml
app:
name: 用户服务
version: 1.0.0
# 业务配置
features:
user-register-enabled: true
user-login-enabled: true
user-delete-enabled: false
# 限流配置
rate-limit:
enabled: true
qps: 1000
burst: 2000
# 缓存配置
cache:
enabled: true
expire-time: 3600
# 消息配置
message:
welcome: "欢迎使用用户服务"
error: "系统繁忙,请稍后重试"
database-config.yaml 示例
yaml
# Nacos 配置中心 - database-config.yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/user_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: root123
# 连接池配置
hikari:
minimum-idle: 5
maximum-pool-size: 20
idle-timeout: 30000
pool-name: UserHikariCP
max-lifetime: 1800000
connection-timeout: 30000
redis-config.yaml 示例
yaml
# Nacos 配置中心 - redis-config.yaml
spring:
data:
redis:
host: localhost
port: 6379
password: redis123
database: 0
timeout: 5000ms
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
max-wait: 3000ms
3.4 配置动态刷新
方式一:@RefreshScope 注解
typescript
package com.example.config;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
/**
* 可刷新的配置类
*/
@Slf4j
@Data
@Component
@RefreshScope // 关键注解:支持配置动态刷新
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String version;
private Features features = new Features();
private RateLimit rateLimit = new RateLimit();
private Cache cache = new Cache();
private Message message = new Message();
@Data
public static class Features {
private Boolean userRegisterEnabled;
private Boolean userLoginEnabled;
private Boolean userDeleteEnabled;
}
@Data
public static class RateLimit {
private Boolean enabled;
private Integer qps;
private Integer burst;
}
@Data
public static class Cache {
private Boolean enabled;
private Integer expireTime;
}
@Data
public static class Message {
private String welcome;
private String error;
}
/**
* 配置变更回调
*/
@RefreshScope
public void onConfigChange() {
log.info("配置已刷新:name={}, version={}", name, version);
}
}
方式二:@NacosConfigListener 监听
typescript
package com.example.listener;
import com.alibaba.cloud.nacos.annotation.NacosConfigListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* Nacos 配置变更监听器
*/
@Slf4j
@Component
public class NacosConfigChangeListener {
/**
* 监听 user-service.yaml 配置变更
*/
@NacosConfigListener(dataId = "user-service.yaml", timeout = 5000)
public void onUserServiceConfigChange(String configInfo) {
log.info("user-service.yaml 配置变更:{}", configInfo);
// 处理配置变更逻辑
}
/**
* 监听 common-config.yaml 配置变更
*/
@NacosConfigListener(dataId = "common-config.yaml", groupId = "DEFAULT_GROUP")
public void onCommonConfigChange(String configInfo) {
log.info("common-config.yaml 配置变更:{}", configInfo);
}
/**
* 监听配置变更(带类型转换)
*/
@NacosConfigListener(dataId = "app-config.yaml", configType = "yaml")
public void onAppConfigChange(AppConfig config) {
log.info("App 配置变更:{}", config);
}
}
方式三:ConfigChangeEvent 事件监听
csharp
package com.example.listener;
import com.alibaba.cloud.nacos.event.NacosConfigEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* Nacos 配置事件监听
*/
@Slf4j
@Component
public class NacosEventListener {
@EventListener
public void handleNacosConfigEvent(NacosConfigEvent event) {
log.info("收到 Nacos 配置事件:dataId={}, groupId={}, namespace={}",
event.getDataId(),
event.getGroupId(),
event.getNamespaceId());
// 处理配置变更
if ("user-service.yaml".equals(event.getDataId())) {
log.info("用户服务配置已更新");
// 执行刷新逻辑
}
}
}
3.5 配置读取示例
kotlin
package com.example.controller;
import com.example.config.AppProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
/**
* 配置演示控制器
*/
@Slf4j
@RefreshScope
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/config")
public class ConfigController {
private final AppProperties appProperties;
// 方式一:@Value 注入
@Value("${app.name:默认服务}")
private String appName;
@Value("${app.version:1.0.0}")
private String appVersion;
@Value("${app.message.welcome:欢迎}")
private String welcomeMessage;
/**
* 获取应用配置
*/
@GetMapping("/app")
public AppProperties getAppConfig() {
log.info("获取应用配置:{}", appName);
return appProperties;
}
/**
* 获取欢迎消息
*/
@GetMapping("/welcome")
public String getWelcome() {
return welcomeMessage;
}
/**
* 获取限流配置
*/
@GetMapping("/rate-limit")
public AppProperties.RateLimit getRateLimit() {
return appProperties.getRateLimit();
}
/**
* 健康检查
*/
@GetMapping("/health")
public String health() {
return "OK - " + appProperties.getName();
}
}
四、Spring Boot 集成 Nacos 服务发现
4.1 服务提供者配置
typescript
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* 服务提供者启动类
*/
@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
4.2 服务注册信息扩展
kotlin
package com.example.config;
import com.alibaba.cloud.nacos.registry.NacosRegistrationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Nacos 注册信息自定义
*/
@Configuration
public class NacosRegistryConfig {
/**
* 自定义服务注册元数据
*/
@Bean
public NacosRegistrationCustomizer registrationCustomizer() {
return registration -> {
// 添加自定义元数据
registration.getMetadata().put("version", "1.0.0");
registration.getMetadata().put("region", "cn-east");
registration.getMetadata().put("zone", "zone-1");
registration.getMetadata().put("gray", "false");
registration.getMetadata().put("startup-time",
String.valueOf(System.currentTimeMillis()));
};
}
}
4.3 服务消费者配置
方式一:RestTemplate + LoadBalancer
kotlin
package com.example.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* RestTemplate 负载均衡配置
*/
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced // 启用负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
arduino
package com.example.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
/**
* 服务调用示例
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
private final RestTemplate restTemplate;
/**
* 调用用户服务
*/
public String getUserInfo(Long userId) {
// 使用服务名调用,自动负载均衡
String url = "http://user-service/api/users/" + userId;
return restTemplate.getForObject(url, String.class);
}
}
方式二:OpenFeign 声明式调用
xml
<!-- 添加 Feign 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
typescript
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* 启用 Feign 客户端
*/
@SpringBootApplication
@EnableFeignClients(basePackages = "com.example.client")
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
less
package com.example.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
* Feign 客户端 - 调用用户服务
*/
@FeignClient(
name = "user-service", // 服务名
contextId = "userClient", // 客户端 ID
path = "/api/users", // 基础路径
fallbackFactory = UserClientFallbackFactory.class // 降级处理
)
public interface UserClient {
/**
* 根据 ID 获取用户
*/
@GetMapping("/{id}")
String getUserById(@PathVariable("id") Long id);
/**
* 创建用户
*/
@PostMapping
String createUser(@RequestBody UserDto user);
/**
* 更新用户
*/
@PutMapping("/{id}")
String updateUser(@PathVariable("id") Long id, @RequestBody UserDto user);
/**
* 删除用户
*/
@DeleteMapping("/{id}")
String deleteUser(@PathVariable("id") Long id);
}
typescript
package com.example.client.fallback;
import com.example.client.UserClient;
import com.example.client.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* Feign 降级工厂
*/
@Slf4j
@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
log.error("用户服务调用失败", cause);
return new UserClient() {
@Override
public String getUserById(Long id) {
return "用户服务暂时不可用";
}
@Override
public String createUser(UserDto user) {
return "创建失败:用户服务不可用";
}
@Override
public String updateUser(Long id, UserDto user) {
return "更新失败:用户服务不可用";
}
@Override
public String deleteUser(Long id) {
return "删除失败:用户服务不可用";
}
};
}
}
4.4 服务健康检查
kotlin
package com.example.health;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
/**
* Nacos 服务健康检查
*/
@Component
@RequiredArgsConstructor
public class NacosHealthIndicator implements HealthIndicator {
private final NacosDiscoveryProperties discoveryProperties;
@Override
public Health health() {
try {
// 检查 Nacos 连接状态
if (discoveryProperties.isRegisterEnabled()) {
return Health.up()
.withDetail("server-addr", discoveryProperties.getServerAddr())
.withDetail("namespace", discoveryProperties.getNamespace())
.withDetail("group", discoveryProperties.getGroup())
.build();
}
return Health.down()
.withDetail("reason", "服务注册已禁用")
.build();
} catch (Exception e) {
return Health.down(e)
.withDetail("reason", "Nacos 连接失败")
.build();
}
}
}
五、生产级最佳实践
5.1 多环境配置管理
python
# Nacos 多环境配置策略
┌─────────────────────────────────────────────────────────────┐
│ 环境 │ Namespace │ Data ID 命名规则 │
├──────────┼───────────────┼─────────────────────────────────│
│ 开发 │ dev-ns-id │ {service}-{profile}.yaml │
│ 测试 │ test-ns-id │ {service}-{profile}.yaml │
│ 预发 │ stage-ns-id │ {service}-{profile}.yaml │
│ 生产 │ prod-ns-id │ {service}-{profile}.yaml │
└─────────────────────────────────────────────────────────────┘
yaml
# bootstrap-prod.yml
spring:
cloud:
nacos:
config:
server-addr: nacos-prod.example.com:8848
namespace: prod-namespace-id
group: PROD_GROUP
username: prod-user
password: ${NACOS_PROD_PASSWORD}
encryption:
enabled: true
discovery:
server-addr: nacos-prod.example.com:8848
namespace: prod-namespace-id
group: PROD_GROUP
5.2 配置加密方案
arduino
package com.example.config.encryption;
import com.alibaba.cloud.nacos.parser.NacosDataParserHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 自定义配置加密器
*/
@Slf4j
@Component
public class CustomEncryptor {
private static final String PREFIX = "ENC(";
private static final String SUFFIX = ")";
/**
* 解密配置值
*/
public String decrypt(String encryptedValue) {
if (encryptedValue != null &&
encryptedValue.startsWith(PREFIX) &&
encryptedValue.endsWith(SUFFIX)) {
String cipherText = encryptedValue.substring(
PREFIX.length(),
encryptedText.length() - SUFFIX.length()
);
// 使用 Jasypt 或其他加密库解密
return decryptByJasypt(cipherText);
}
return encryptedValue;
}
private String decryptByJasypt(String cipherText) {
// Jasypt 解密逻辑
return cipherText; // 简化示例
}
}
yaml
# Nacos 配置中的加密值
spring:
datasource:
password: ENC(AES256加密后的密文)
redis:
password: ENC(AES256加密后的密文)
5.3 配置变更审计
java
package com.example.audit;
import com.alibaba.cloud.nacos.event.NacosConfigEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* 配置变更审计
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ConfigAuditListener {
private final ConfigAuditRepository auditRepository;
@EventListener
public void onConfigChange(NacosConfigEvent event) {
ConfigAudit audit = ConfigAudit.builder()
.dataId(event.getDataId())
.groupId(event.getGroupId())
.namespaceId(event.getNamespaceId())
.changeTime(System.currentTimeMillis())
.operator(getCurrentUser())
.build();
auditRepository.save(audit);
log.info("配置变更审计:dataId={}, operator={}, time={}",
event.getDataId(),
getCurrentUser(),
System.currentTimeMillis());
}
private String getCurrentUser() {
// 获取当前操作用户
return "system";
}
}
5.4 高可用配置
yaml
# Nacos 集群配置
spring:
cloud:
nacos:
config:
# 多地址配置(集群)
server-addr: nacos1.example.com:8848,nacos2.example.com:8848,nacos3.example.com:8848
# 连接超时
connect-timeout: 5000
# 请求超时
request-timeout: 10000
# 最大重试
max-retry: 5
# 重试间隔
retry-time: 2000
# 本地缓存
config-cache-dir: /data/nacos/config-cache
# 启用本地缓存
enable-remote-sync-config: true
5.5 监控告警配置
yaml
# Actuator 监控端点
management:
endpoints:
web:
exposure:
include: health,info,metrics,nacos-config,nacos-discovery
endpoint:
health:
show-details: always
nacos-config:
enabled: true
nacos-discovery:
enabled: true
metrics:
export:
prometheus:
enabled: true
health:
nacos:
enabled: true
redis:
enabled: true
db:
enabled: true
六、常见问题排查
6.1 配置不生效
markdown
问题:Nacos 配置修改后未生效
排查步骤:
1. 检查 @RefreshScope 注解是否添加
2. 检查 bootstrap.yml 配置是否正确
3. 检查 Data ID 命名是否匹配
4. 检查 Namespace 是否一致
5. 检查 Actuator 端点是否开启
6. 查看日志:com.alibaba.cloud.nacos
6.2 服务注册失败
markdown
问题:服务无法注册到 Nacos
排查步骤:
1. 检查 Nacos 服务器是否可访问
2. 检查 namespace 配置是否一致
3. 检查服务名是否包含特殊字符
4. 查看 Nacos 控制台服务列表
5. 检查防火墙和网络策略
6. 查看客户端日志
6.3 配置优先级问题
markdown
Spring Boot 配置优先级(高→低):
1. 命令行参数
2. SPRING_APPLICATION_JSON
3. ServletConfig/ServletContext 参数
4. JNDI 属性
5. Java System Properties
6. 操作系统环境变量
7. RandomValuePropertySource
8. jar 包外 application-{profile}.yml
9. jar 包内 application-{profile}.yml
10. jar 包外 application.yml
11. jar 包内 application.yml
12. @PropertySource
13. 默认属性
14. Nacos 配置中心(通过 bootstrap 加载)
七、性能优化建议
7.1 客户端优化
yaml
spring:
cloud:
nacos:
config:
# 启用长轮询
long-polling-timeout: 30000
# 启用本地缓存
enable-remote-sync-config: true
# 缓存目录
config-cache-dir: /data/nacos/cache
discovery:
# 心跳间隔优化
heart-beat-interval: 5000
# 心跳超时
heart-beat-timeout: 15000
# 实例元数据压缩
metadata-compress: true
7.2 服务端优化
ini
# Nacos 服务器配置 - application.properties
# 集群节点数
nacos.core.cluster.default.node.timeout=3000
# 配置快照间隔
nacos.config.snapshot.interval=30
# 长轮询任务数
nacos.config.long-polling.task-count=200
# 长轮询最大连接数
nacos.config.long-polling.max-client=10000
# 配置数据缓存
nacos.config.cache.enable=true
八、总结
核心要点回顾
java
┌─────────────────────────────────────────────────────────────┐
│ Spring Boot + Nacos 集成要点 │
├─────────────────────────────────────────────────────────────┤
│ ✅ 依赖版本:Spring Cloud Alibaba 2023.0.x + Nacos 2.3.x │
│ ✅ 配置文件:bootstrap.yml + application.yml │
│ ✅ 配置中心:@RefreshScope + @NacosConfigListener │
│ ✅ 服务发现:@EnableDiscoveryClient + @FeignClient │
│ ✅ 多环境:Namespace 隔离 + Profile 激活 │
│ ✅ 安全性:配置加密 + 认证授权 + 审计日志 │
│ ✅ 高可用:集群部署 + 本地缓存 + 健康检查 │
└─────────────────────────────────────────────────────────────┘
学习路线建议
入门 → 进阶 → 精通
│ │ │
│ │ └── 源码分析
│ │ └── 性能调优
│ │ └── 高可用架构
│ └── 多环境管理
│ └── 配置加密
│ └── 服务治理
└── 基础集成
└── 配置中心
└── 服务发现