Nacos详解
1835字约6分钟
2025-08-16
什么是Nacos
Nacos是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos致力于帮助您发现、配置和管理微服务,提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
主要特性
- 服务注册与发现:支持多种服务注册方式,包括DNS、RPC等
- 配置管理:支持配置的动态更新、版本管理、灰度发布等
- 服务管理:提供服务健康检查、服务路由、负载均衡等
- 命名空间:支持多环境、多租户的隔离
- 集群管理:支持集群部署和扩展
- 多数据中心:支持多数据中心的部署
核心功能
1. 服务注册与发现
- 服务注册:服务提供者向注册中心注册服务信息
- 服务发现:服务消费者从注册中心获取服务列表
- 服务健康检查:定期检查服务状态,自动剔除不健康服务
2. 配置管理
- 配置发布:支持配置的动态发布和更新
- 配置版本管理:支持配置的版本控制和回滚
- 配置灰度发布:支持配置的灰度发布和A/B测试
3. 服务管理
- 服务路由:支持基于规则的服务路由
- 负载均衡:支持多种负载均衡策略
- 流量管理:支持流量控制和熔断
安装和部署
1. 单机模式安装
# 下载Nacos
wget https://github.com/alibaba/nacos/releases/download/2.2.3/nacos-server-2.2.3.tar.gz
# 解压
tar -xvf nacos-server-2.2.3.tar.gz
cd nacos/bin
# 启动单机模式
sh startup.sh -m standalone2. Docker安装
# 拉取镜像
docker pull nacos/nacos-server:v2.2.3
# 运行容器
docker run -d --name nacos-standalone \
-p 8848:8848 \
-p 9848:9848 \
-e MODE=standalone \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=localhost \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=password \
nacos/nacos-server:v2.2.33. 数据库初始化
-- 创建数据库
CREATE DATABASE nacos DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 执行初始化脚本
-- 脚本位置:nacos/conf/nacos-mysql.sql4. 访问控制台
- URL: http://localhost:8848/nacos
- 默认用户名: nacos
- 默认密码: nacos
服务注册与发现
1. SpringBoot集成
添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>配置文件
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: public
group: DEFAULT_GROUP
cluster-name: DEFAULT
enabled: true
register-enabled: true
ephemeral: true
metadata:
version: 1.0.0
zone: zone1启动类
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}服务注册
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/info")
public String getUserInfo() {
List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
if (!instances.isEmpty()) {
ServiceInstance instance = instances.get(0);
return String.format("服务地址: %s:%d", instance.getHost(), instance.getPort());
}
return "服务不可用";
}
}2. 服务发现
@Service
public class UserService {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
public String callOtherService() {
// 通过负载均衡选择服务实例
ServiceInstance instance = loadBalancerClient.choose("order-service");
if (instance != null) {
String url = String.format("http://%s:%d/order/list",
instance.getHost(), instance.getPort());
return restTemplate.getForObject(url, String.class);
}
return "服务不可用";
}
}3. 服务健康检查
@Component
public class NacosHealthIndicator implements HealthIndicator {
@Autowired
private NacosServiceRegistry nacosServiceRegistry;
@Override
public Health health() {
try {
// 检查Nacos连接状态
if (nacosServiceRegistry != null) {
return Health.up()
.withDetail("nacos", "connected")
.build();
} else {
return Health.down()
.withDetail("nacos", "disconnected")
.build();
}
} catch (Exception e) {
return Health.down()
.withException(e)
.build();
}
}
}配置管理
1. 配置发布
通过控制台发布配置
- 登录Nacos控制台
- 选择"配置管理" -> "配置列表"
- 点击"+"按钮创建配置
- 填写配置信息:
- Data ID: user-service-dev.yaml
- Group: DEFAULT_GROUP
- 配置格式: YAML
- 配置内容: 填写具体的配置项
通过API发布配置
@Component
public class NacosConfigService {
@Autowired
private NacosConfigManager nacosConfigManager;
public void publishConfig(String dataId, String group, String content) {
try {
boolean result = nacosConfigManager.getConfigService()
.publishConfig(dataId, group, content);
if (result) {
System.out.println("配置发布成功");
} else {
System.out.println("配置发布失败");
}
} catch (NacosException e) {
e.printStackTrace();
}
}
}2. SpringBoot配置集成
添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>配置文件
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
namespace: public
group: DEFAULT_GROUP
file-extension: yaml
shared-configs:
- data-id: common-config.yaml
group: DEFAULT_GROUP
refresh: true
extension-configs:
- data-id: extension-config.yaml
group: DEFAULT_GROUP
refresh: true配置类
@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "user")
@Data
public class UserConfig {
private String name;
private int age;
private String email;
}使用配置
@RestController
@RequestMapping("/config")
public class ConfigController {
@Autowired
private UserConfig userConfig;
@Value("${user.name:default}")
private String userName;
@GetMapping("/user")
public UserConfig getUserConfig() {
return userConfig;
}
@GetMapping("/name")
public String getUserName() {
return userName;
}
}3. 配置监听
@Component
public class ConfigChangeListener {
@NacosConfigListener(dataId = "user-service-dev.yaml", groupId = "DEFAULT_GROUP")
public void onConfigChange(String newConfig) {
System.out.println("配置发生变化: " + newConfig);
// 处理配置变化逻辑
}
}集群部署
1. 集群架构
[负载均衡器]
|
+----------------+----------------+
| | |
[Nacos1] [Nacos2] [Nacos3]
| | |
+----------------+----------------+
|
[MySQL集群]2. 集群配置
修改cluster.conf
# 编辑nacos/conf/cluster.conf
192.168.1.10:8848
192.168.1.11:8848
192.168.1.12:8848修改application.properties
# 集群模式
spring.cloud.nacos.discovery.cluster-name=CLUSTER_001
# 数据库配置
spring.datasource.platform=mysql
db.url.0=jdbc:mysql://192.168.1.20:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=password
# 集群配置
nacos.core.protocol.raft.data.dir=${nacos.home}/data/protocol/raft
nacos.core.protocol.raft.snapshot.dir=${nacos.home}/data/protocol/raft/snapshot3. 启动集群
# 在每个节点上启动
sh startup.sh
# 检查集群状态
curl http://localhost:8848/nacos/v1/ns/operator/metricsSpringCloud集成
1. 服务注册与发现
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: public
group: DEFAULT_GROUP
cluster-name: DEFAULT
enabled: true
register-enabled: true
ephemeral: true
metadata:
version: 1.0.0
zone: zone12. 配置管理
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
namespace: public
group: DEFAULT_GROUP
file-extension: yaml
shared-configs:
- data-id: common-config.yaml
group: DEFAULT_GROUP
refresh: true3. 负载均衡
@Configuration
public class LoadBalancerConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}最佳实践
1. 命名空间管理
# 开发环境
spring:
cloud:
nacos:
discovery:
namespace: dev
config:
namespace: dev
# 测试环境
spring:
cloud:
nacos:
discovery:
namespace: test
config:
namespace: test
# 生产环境
spring:
cloud:
nacos:
discovery:
namespace: prod
config:
namespace: prod2. 配置分组管理
# 公共配置
spring:
cloud:
nacos:
config:
shared-configs:
- data-id: common-config.yaml
group: COMMON_GROUP
refresh: true
# 业务配置
spring:
cloud:
nacos:
config:
shared-configs:
- data-id: business-config.yaml
group: BUSINESS_GROUP
refresh: true3. 服务元数据管理
@Component
public class ServiceMetadataManager {
@Autowired
private NacosServiceRegistry nacosServiceRegistry;
public void updateMetadata(String serviceId, Map<String, String> metadata) {
Registration registration = new Registration() {
@Override
public String getServiceId() {
return serviceId;
}
@Override
public String getHost() {
return "localhost";
}
@Override
public int getPort() {
return 8080;
}
@Override
public boolean isSecure() {
return false;
}
@Override
public URI getUri() {
return URI.create("http://localhost:8080");
}
@Override
public Map<String, String> getMetadata() {
return metadata;
}
@Override
public String getScheme() {
return "http";
}
};
nacosServiceRegistry.register(registration);
}
}4. 配置加密
@Component
public class ConfigEncryptor {
private static final String SECRET_KEY = "your-secret-key";
public String encrypt(String plainText) {
try {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
} catch (Exception e) {
throw new RuntimeException("加密失败", e);
}
}
public String decrypt(String encryptedText) {
try {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
return new String(decrypted);
} catch (Exception e) {
throw new RuntimeException("解密失败", e);
}
}
}监控和运维
1. 健康检查
@Component
public class NacosHealthIndicator implements HealthIndicator {
@Autowired
private NamingService namingService;
@Override
public Health health() {
try {
// 检查Nacos连接状态
namingService.getServicesOfServer(1, Integer.MAX_VALUE);
return Health.up()
.withDetail("nacos", "connected")
.build();
} catch (Exception e) {
return Health.down()
.withException(e)
.build();
}
}
}2. 指标监控
@Component
public class NacosMetrics {
private final Counter serviceRegisterCounter;
private final Timer configUpdateTimer;
public NacosMetrics(MeterRegistry meterRegistry) {
this.serviceRegisterCounter = Counter.builder("nacos.service.register.total")
.description("Total number of service registrations")
.register(meterRegistry);
this.configUpdateTimer = Timer.builder("nacos.config.update.duration")
.description("Config update duration")
.register(meterRegistry);
}
public void incrementServiceRegisterCount() {
serviceRegisterCounter.increment();
}
public Timer.Sample startConfigUpdateTimer() {
return Timer.start();
}
}3. 日志配置
logging:
level:
com.alibaba.nacos: DEBUG
com.alibaba.cloud: DEBUG
file:
name: logs/nacos-client.log常见问题
1. 服务注册失败
- 检查Nacos服务是否正常运行
- 确认网络连接是否正常
- 检查配置是否正确
2. 配置更新不生效
- 确认配置的Data ID和Group是否正确
- 检查是否添加了@RefreshScope注解
- 确认配置的刷新策略
3. 集群节点无法通信
- 检查cluster.conf配置是否正确
- 确认网络防火墙设置
- 检查节点间的网络连通性
4. 性能问题
- 调整连接池大小
- 优化配置更新频率
- 使用集群部署提高可用性
