**作者:洛水石** | **更新日期:2026-05-11** | **标签:Nacos | Spring Cloud | 微服务 | 服务治理**

前言

上周二早上9点,线上告警炸了:服务A调用服务B失败,500+错误。查了半天发现是服务B重启后IP变了,服务A还在用旧的IP调用。

这不是个案。在微服务架构中,**服务实例是动态的**,IP会变、端口会变、数量会动态伸缩。传统的配置文件方式根本无法应对这种变化。

Nacos就是来解决这个问题的——**服务注册与发现、配置管理、服务健康监测**,让你告别硬编码,拥抱动态服务治理。

一、Nacos核心概念

 1.1 服务注册与发现原理

▲ Nacos服务注册发现架构

**核心流程**

  1. 服务提供者启动时向Nacos注册自己的信息
  2. 服务消费者从Nacos获取服务提供者的实例列表
  3. Nacos感知到服务变化时主动通知消费者

 1.2 命名空间与隔离

隔离级别

说明

使用场景

**Namespace**

顶级隔离,不同环境

dev/test/prod

**Group**

服务分组

业务线/团队划分

**DataID**

具体配置

配置文件

二、快速部署

 2.1 Docker Compose部署

# docker-compose.yml
version: '3.8'
services:
  nacos:
    image: nacos/nacos-server:v2.2.3
    container_name: nacos
    environment:
      MODE: standalone
      SPRING_DATASOURCE_PLATFORM: embedded
    ports:
      - "8848:8848"
      - "9848:9848"
    volumes:
      - ./data:/home/nacos/data
      - ./logs:/home/nacos/logs
    restart: unless-stopped

# 启动
docker-compose up -d

# 访问控制台
# http://localhost:8848/nacos
# 默认账号密码: nacos / nacos

 2.2 Kubernetes部署

# nacos.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-standalone-config
data:
  MODE: "standalone"
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos
spec:
  serviceName: nacos
  replicas: 1
  selector:
    matchLabels:
      app: nacos
  template:
    metadata:
      labels:
        app: nacos
    spec:
      containers:
      - name: nacos
        image: nacos/nacos-server:v2.2.3
        ports:
        - containerPort: 8848
          name: client
        - containerPort: 9848
          name: grpc
        env:
        - name: MODE
          valueFrom:
            configMapKeyRef:
              name: nacos-standalone-config
              key: MODE
        resources:
          requests:
            memory: 1Gi
            cpu: 500m
          limits:
            memory: 2Gi
            cpu: 1000m

三、Spring Boot集成

 3.1 依赖配置

<!-- pom.xml -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2022.0.0.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2022.0.0.0</version>
</dependency>

 3.2 application.yml

# bootstrap.yml (注意是bootstrap不是application)
spring:
  application:
    name: order-service
  cloud:
    nacos:
      server-addr: 192.168.1.100:8848
      username: nacos
      password: nacos
      discovery:
        namespace: dev
        group: DEFAULT_GROUP
        metadata:
          version: v1
      config:
        namespace: dev
        group: DEFAULT_GROUP
        file-extension: yaml
        refresh-enabled: true
        shared-configs:
          - data-id: common.yaml
            group: GLOBAL
            refresh: true

 3.3 服务注册

@SpringBootApplication
@EnableDiscoveryClient  // 启用服务发现
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

// 服务启动后自动注册到Nacos
@RestController
public class HealthController {
    @GetMapping("/health")
    public String health() {
        return "OK";
    }
}

 3.4 服务调用

@Service
public class OrderService {

    @Autowired
    private RestTemplate restTemplate;

    // 方式1:服务名直接调用(Ribbon负载均衡)
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public Order createOrder(Long productId, Integer quantity) {
        // 通过服务名调用,不需要知道IP和端口
        Product product = restTemplate.getForObject(
            "http://product-service/api/products/" + productId,
            Product.class
        );
        // ... 创建订单
        return order;
    }
}

 3.5 使用Feign调用

// 定义Feign客户端
@FeignClient(name = "product-service", path = "/api/products")
public interface ProductClient {

    @GetMapping("/{id}")
    Product getProduct(@PathVariable("id") Long id);

    @GetMapping("/{id}/stock")
    Integer getStock(@PathVariable("id") Long id);
}

// 使用
@Service
public class OrderService {

    @Autowired
    private ProductClient productClient;

    public Order createOrder(Long productId) {
        Product product = productClient.getProduct(productId);
        // ... 创建订单
        return order;
    }
}

四、配置中心

 4.1 在Nacos创建配置

▲ 配置中心工作流程

# Data ID: order-service.yaml
# Group: DEFAULT_GROUP
# Namespace: dev

spring:
  datasource:
    url: jdbc:mysql://mysql:3306/orders?useSSL=false
    username: root
    password: ${DB_PASSWORD:default123}
    driver-class-name: com.mysql.cj.jdbc.Driver

server:
  port: ${SERVER_PORT:8080}

order:
  timeout: 5000
  max-retry: 3
  payment-url: http://payment-service/api/pay

 4.2 动态获取配置

@RestController
@RefreshScope  // 启用动态刷新
public class OrderConfig {

    @Value("${order.timeout:3000}")
    private Integer timeout;

    @Value("${order.max-retry:3}")
    private Integer maxRetry;

    @GetMapping("/config")
    public Map<String, Object> getConfig() {
        Map<String, Object> config = new HashMap<>();
        config.put("timeout", timeout);
        config.put("maxRetry", maxRetry);
        return config;
    }
}

 4.3 配置监听

@Component
@Slf4j
public class NacosConfigListener {

    @NacosConfigListener(dataId = "order-service.yaml", groupId = "DEFAULT_GROUP")
    public void onConfigChange(String config) {
        log.info("配置变更: {}", config);
        // 处理配置变更
        // 例如:重新初始化连接池、刷新缓存等
    }
}

 4.4 共享配置

# 共享配置 - 多个服务共用
# Data ID: common.yaml
# Group: GLOBAL

# 日志配置
logging:
  level:
    root: INFO
    com.example: DEBUG
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

# Swagger配置
swagger:
  enabled: true
  title: API文档
  version: 1.0

五、服务治理

 5.1 负载均衡权重

// 服务实例级别设置权重
@Configuration
public class RibbonConfig {

    @Bean
    public IRule ribbonRule() {
        // 权重负载均衡 - 根据权重分配流量
        return new WeightedResponseTimeRule();
    }
}

 5.2 熔断降级

@FeignClient(name = "product-service", fallback = ProductClientFallback.class)
public interface ProductClient {

    @GetMapping("/{id}")
    Product getProduct(@PathVariable("id") Long id);
}

// 降级实现
@Component
@Slf4j
public class ProductClientFallback implements ProductClient {

    @Override
    public Product getProduct(Long id) {
        log.warn("Product服务调用失败,返回降级数据");
        Product fallbackProduct = new Product();
        fallbackProduct.setId(id);
        fallbackProduct.setName("降级商品");
        fallbackProduct.setPrice(BigDecimal.ZERO);
        return fallbackProduct;
    }
}

 5.3 命名空间隔离

# bootstrap.yml
spring:
  cloud:
    nacos:
      discovery:
        namespace: ${NACOS_NAMESPACE}  # 指定命名空间
        group: ${SERVICE_GROUP}        # 指定分组

// Java中获取某命名空间的服务
@Autowired
private NamingService namingService;

public List<Instance> getInstances(String serviceName) {
    try {
        return namingService.selectInstances(serviceName, true);
    } catch (NacosException e) {
        log.error("获取服务实例失败", e);
        return Collections.emptyList();
    }
}

六、生产最佳实践

 6.1 高可用部署

▲ Nacos高可用集群架构

# nacos-cluster.yaml
version: '3.8'
services:
  nacos1:
    image: nacos/nacos-server:v2.2.3
    container_name: nacos1
    environment:
      MODE: cluster
      NACOS_SERVERS: nacos1:8848 nacos2:8848 nacos3:8848
      MYSQL_HOST: mysql
      MYSQL_DB_NAME: nacos
      MYSQL_USER: nacos
      MYSQL_PASSWORD: nacos123
    ports:
      - "8848:8848"
    depends_on:
      - mysql

  nacos2:
    image: nacos/nacos-server:v2.2.3
    container_name: nacos2
    environment:
      MODE: cluster
      NACOS_SERVERS: nacos1:8848 nacos2:8848 nacos3:8848
      MYSQL_HOST: mysql
      MYSQL_DB_NAME: nacos
      MYSQL_USER: nacos
      MYSQL_PASSWORD: nacos123
    ports:
      - "8849:8848"

  nacos3:
    image: nacos/nacos-server:v2.2.3
    container_name: nacos3
    environment:
      MODE: cluster
      NACOS_SERVERS: nacos1:8848 nacos2:8848 nacos3:8848
      MYSQL_HOST: mysql
      MYSQL_DB_NAME: nacos
      MYSQL_USER: nacos
      MYSQL_PASSWORD: nacos123
    ports:
      - "8850:8848"

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: nacos
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

 6.2 配置加密

// 配置属性加密
@Configuration
public class NacosConfig {

    @NacosConfigurationProperties(prefix = "spring.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }
}

// 使用加密配置
spring:
  datasource:
    password: '{cipher}xxx加密后的密码xxx'

七、常见问题

 Q1: 服务注册后发现实例不存在?

# 检查网络连通性
curl http://192.168.1.100:8848/nacos/v1/ns/instance/list?serviceName=order-service

# 检查服务实例元数据
curl http://192.168.1.100:8848/nacos/v1/ns/instance/metadata?serviceName=order-service

 Q2: 配置更新后没有生效?

// 检查是否添加了 @RefreshScope
@RestController
@RefreshScope  // 必须添加!
public class ConfigController {
    @Value("${custom.config}")
    private String config;
}

 Q3: 服务下线后仍被调用?

// 确保正确下线
@PreDestroy
public void deregister() {
    try {
        nacosServiceManager.getNamingService().deregisterInstance(
            serviceName, ip, port
        );
    } catch (NacosException e) {
        log.error("服务注销失败", e);
    }
}

总结

Nacos核心能力一览:

能力

说明

收益

**服务注册**

自动注册、心跳检测

免去手动维护服务列表

**服务发现**

动态获取、实时通知

告别硬编码IP

**配置管理**

集中管理、动态刷新

配置变更无需重启

**命名空间**

环境隔离、逻辑分区

支持多环境部署

**高可用**

集群模式、数据持久化

生产环境必备

**下一步建议**

  1. 集成Sentinel实现流量控制
  2. 接入SkyWalking实现链路追踪
  3. 配置Prometheus监控

*微服务架构,Nacos让服务治理变得简单。*

更多推荐