Skip to content

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:8848

application.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=1g

MySQL数据库初始化

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作为阿里云原生应用的重要基础设施,提供了完整的服务治理能力,通过其强大的服务发现和配置管理功能,极大简化了微服务架构的复杂性,是构建云原生应用的理想选择。

正在精进