Nacos
Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
核心功能
服务发现
- 服务注册 - 服务提供者注册服务实例信息
- 服务发现 - 服务消费者查询可用服务实例
- 健康检查 - 定期检查服务实例健康状态
- 负载均衡 - 支持多种负载均衡策略
配置管理
- 动态配置 - 运行时动态更新应用配置
- 配置热更新 - 配置变更实时推送到应用
- 配置版本管理 - 支持配置历史版本管理
- 灰度发布 - 配置变更灰度推送
服务管理
- 命名空间 - 多环境配置隔离
- 服务分组 - 服务逻辑分组管理
- 元数据管理 - 服务实例元数据管理
- 流量管理 - 服务流量控制和治理
架构设计
核心组件
- Nacos Server - 服务端,提供服务注册、配置管理等功能
- Nacos Client - 客户端SDK,与服务端交互
- Console - 控制台,提供Web管理界面
- MySQL - 可选的外部数据存储
部署模式
单机模式 (Standalone)
├── Nacos Server
└── 内嵌数据库
集群模式 (Cluster)
├── Nacos Server 1
├── Nacos Server 2
├── Nacos Server 3
├── MySQL 数据库
└── Nginx 负载均衡服务发现
Spring Cloud集成
服务提供者
xml
<!-- 添加依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>点击查看完整代码实现
yaml
# application.yml配置
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
group: DEFAULT_GROUP
cluster-name: BJ
metadata:
version: 1.0.0
zone: beijing
server:
port: 8080
management:
endpoints:
web:
exposure:
include: "*"java
// 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}服务消费者
点击查看完整代码实现
java
// Feign客户端
@FeignClient(name = "user-service")
public interface UserServiceClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}
// 使用RestTemplate
@RestController
public class OrderController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/orders/{orderId}/user")
public User getUserByOrderId(@PathVariable String orderId) {
// 手动负载均衡
ServiceInstance instance = loadBalancerClient.choose("user-service");
String url = String.format("http://%s:%s/users/1",
instance.getHost(), instance.getPort());
return restTemplate.getForObject(url, User.class);
}
}
// 配置类
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}原生API使用
服务注册
点击查看完整代码实现
java
import com.alibaba.nacos.api.naming.NacosNamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
public class ServiceRegistry {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("serverAddr", "127.0.0.1:8848");
properties.setProperty("namespace", "dev");
NamingService namingService = NacosNamingFactory.createNamingService(properties);
// 注册服务实例
Instance instance = new Instance();
instance.setIp("192.168.1.100");
instance.setPort(8080);
instance.setHealthy(true);
instance.setWeight(2.0);
Map<String, String> metadata = new HashMap<>();
metadata.put("version", "1.0.0");
metadata.put("env", "prod");
instance.setMetadata(metadata);
namingService.registerInstance("user-service", "DEFAULT_GROUP", instance);
}
}服务发现
点击查看完整代码实现
java
public class ServiceDiscovery {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("serverAddr", "127.0.0.1:8848");
NamingService namingService = NacosNamingFactory.createNamingService(properties);
// 获取健康实例
List<Instance> instances = namingService.selectInstances("user-service", true);
// 订阅服务变更
namingService.subscribe("user-service", new EventListener() {
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent) {
NamingEvent namingEvent = (NamingEvent) event;
System.out.println("服务实例发生变更: " + namingEvent.getInstances());
}
}
});
}
}配置管理
Spring Cloud Config集成
xml
<!-- 添加依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>点击查看完整代码实现
yaml
# bootstrap.yml配置
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: dev
group: DEFAULT_GROUP
prefix: ${spring.application.name}
refresh-enabled: true
profiles:
active: dev配置文件示例
在Nacos控制台创建配置
点击查看完整代码实现
yaml
# Data ID: user-service-dev.yaml
# Group: DEFAULT_GROUP
# 内容:
server:
port: 8080
database:
host: localhost
port: 3306
name: user_db
username: root
password: 123456
redis:
host: localhost
port: 6379
timeout: 3000
business:
feature:
newFeature: true
settings:
maxConnections: 100动态配置刷新
点击查看完整代码实现
java
// 使用@RefreshScope注解
@RestController
@RefreshScope
public class ConfigController {
@Value("${business.settings.maxConnections:50}")
private int maxConnections;
@Value("${business.feature.newFeature:false}")
private boolean newFeatureEnabled;
@GetMapping("/config/info")
public Map<String, Object> getConfig() {
Map<String, Object> config = new HashMap<>();
config.put("maxConnections", maxConnections);
config.put("newFeatureEnabled", newFeatureEnabled);
return config;
}
}
// 配置属性类
@Component
@ConfigurationProperties(prefix = "database")
@RefreshScope
@Data
public class DatabaseConfig {
private String host;
private int port;
private String name;
private String username;
private String password;
}原生配置API
点击查看完整代码实现
java
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
public class ConfigExample {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("serverAddr", "127.0.0.1:8848");
properties.put("namespace", "dev");
ConfigService configService = ConfigFactory.createConfigService(properties);
// 获取配置
String dataId = "user-service-dev.yaml";
String group = "DEFAULT_GROUP";
String config = configService.getConfig(dataId, group, 5000);
System.out.println("配置内容: " + config);
// 发布配置
boolean result = configService.publishConfig(dataId, group, "新的配置内容");
System.out.println("发布结果: " + result);
// 添加配置监听器
configService.addListener(dataId, group, new Listener() {
@Override
public Executor getExecutor() {
return null;
}
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("配置发生变更: " + configInfo);
// 处理配置变更逻辑
}
});
}
}集群部署
集群配置
cluster.conf配置
bash
# cluster.conf文件
192.168.1.101:8848
192.168.1.102:8848
192.168.1.103:8848application.properties配置
properties
# 服务端口
server.port=8848
# 数据库配置
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.1.100:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=nacos
db.password.0=nacos
# JVM参数
JVM_XMS=2g
JVM_XMX=2g
JVM_XMN=1gMySQL数据库初始化
sql
-- 创建数据库
CREATE DATABASE nacos DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
-- 创建用户
CREATE USER 'nacos'@'%' IDENTIFIED BY 'nacos';
GRANT ALL PRIVILEGES ON nacos.* TO 'nacos'@'%';
FLUSH PRIVILEGES;
-- 执行初始化脚本(nacos/conf/nacos-mysql.sql)Nginx负载均衡
点击查看完整代码实现
nginx
upstream nacos_cluster {
server 192.168.1.101:8848;
server 192.168.1.102:8848;
server 192.168.1.103:8848;
}
server {
listen 80;
server_name nacos.example.com;
location / {
proxy_pass http://nacos_cluster;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}高级功能
命名空间管理
java
// 不同环境使用不同命名空间
# 开发环境
spring.cloud.nacos.config.namespace=dev
spring.cloud.nacos.discovery.namespace=dev
# 测试环境
spring.cloud.nacos.config.namespace=test
spring.cloud.nacos.discovery.namespace=test
# 生产环境
spring.cloud.nacos.config.namespace=prod
spring.cloud.nacos.discovery.namespace=prod配置加密
点击查看完整代码实现
java
// 自定义配置解密
@Component
public class ConfigDecryption implements ConfigurationCustomizer {
@Override
public void customize(ConfigurationBuilder builder) {
builder.withConfigService(new DecryptConfigService());
}
private class DecryptConfigService implements ConfigService {
@Override
public String getConfig(String dataId, String group, long timeoutMs) {
String encryptedConfig = originalConfigService.getConfig(dataId, group, timeoutMs);
return decrypt(encryptedConfig);
}
private String decrypt(String encrypted) {
// 实现解密逻辑
return encrypted;
}
}
}灰度发布
yaml
# 创建灰度配置
# Data ID: user-service-dev.yaml
# Group: GRAY_GROUP
# 内容: 灰度环境的配置
# 应用配置
spring:
cloud:
nacos:
config:
group: ${config.group:DEFAULT_GROUP}
# 通过启动参数控制
java -jar app.jar --config.group=GRAY_GROUP监控和管理
监控指标
bash
# 服务注册数量
curl http://localhost:8848/nacos/v1/ns/operator/metrics
# 配置数量统计
curl http://localhost:8848/nacos/v1/cs/configs?dataId=&group=&pageNo=1&pageSize=100
# 集群节点状态
curl http://localhost:8848/nacos/v1/core/cluster/nodes健康检查
bash
# 服务端健康检查
curl http://localhost:8848/nacos/actuator/health
# 客户端健康检查
curl http://localhost:8080/actuator/health日志配置
xml
<!-- logback-spring.xml -->
<configuration>
<springProfile name="dev">
<logger name="com.alibaba.nacos" level="DEBUG"/>
</springProfile>
<springProfile name="prod">
<logger name="com.alibaba.nacos" level="WARN"/>
</springProfile>
</configuration>最佳实践
服务注册发现
- 合理设置健康检查间隔
- 使用元数据传递版本信息
- 配置适当的负载均衡策略
- 监控服务注册状态
配置管理
- 敏感信息加密存储
- 使用命名空间隔离环境
- 建立配置版本管理规范
- 实现配置变更审计
运维管理
- 部署高可用集群
- 定期备份配置数据
- 监控系统资源使用
- 建立故障应急预案
安全配置
- 开启访问控制(ACL)
- 配置SSL/TLS加密
- 限制网络访问范围
- 定期更新密码策略
Nacos作为阿里云原生应用的重要基础设施,提供了完整的服务治理能力,通过其强大的服务发现和配置管理功能,极大简化了微服务架构的复杂性,是构建云原生应用的理想选择。
