一、为什么我们需要 Nacos?

在讲 Nacos 之前,我们先搞清楚微服务架构下的两个核心痛点。

痛点 1:服务发现问题

在单体架构中,服务之间的调用就是本地方法调用,非常简单。但在微服务架构中,一个系统被拆分成了几十个甚至上百个服务,每个服务都部署在多个节点上。

这时候就出现了一个问题:服务 A 如何知道服务 B 的所有实例地址?

如果没有注册中心,你只能在配置文件中写死服务 B 的所有地址。但当服务 B 扩容、缩容、节点宕机时,你需要手动修改所有依赖服务 B 的配置文件,这在微服务架构下是完全不可行的。

痛点 2:配置管理问题

每个微服务都有自己的配置文件,当服务数量越来越多时,配置管理就变成了一场灾难:

  • 配置分散在各个服务中,难以统一管理
  • 修改配置需要重新打包、部署、重启服务
  • 不同环境(开发、测试、生产)的配置难以隔离
  • 配置变更没有版本控制,出了问题无法回滚

而 Nacos 就是为了解决这两个痛点而生的。它是一个集服务注册发现、配置管理、服务治理于一体的开源平台,由阿里巴巴开源,是 Spring Cloud Alibaba 生态的核心组件。

Nacos 的核心优势

  • 一站式解决方案:同时提供注册中心和配置中心功能,不需要部署多个组件
  • 简单易用:提供 Web 管理界面,操作简单,一分钟就能上手
  • 高可用:支持集群部署,保证服务的高可用性
  • 动态配置:配置修改后实时生效,不需要重启服务
  • 丰富的服务治理功能:支持服务权重、负载均衡、熔断降级、流量控制等
  • 多语言支持:支持 Java、Go、Python、Node.js 等多种语言

二、Nacos 核心概念

要真正用好 Nacos,必须先搞懂它的核心概念。

1. 命名空间(Namespace)

命名空间是 Nacos 中最高级别的隔离单元,用于隔离不同环境的配置和服务。比如你可以创建三个命名空间:dev(开发环境)、test(测试环境)、prod(生产环境),不同命名空间之间的配置和服务完全隔离。

2. 分组(Group)

分组是命名空间下的二级隔离单元,用于将不同的服务或配置进行分组管理。比如你可以将同一个项目的所有服务和配置都放在同一个分组下。

3. 服务(Service)

服务是微服务架构中的基本单元,对应一个应用程序。每个服务都有一个唯一的名称,比如user-serviceorder-service

4. 实例(Instance)

实例是服务的一个具体运行节点,对应一个 JVM 进程。每个实例都有自己的 IP 地址、端口号和健康状态。

5. 集群(Cluster)

集群是服务下的实例分组,用于将同一个服务的不同实例进行分组管理。比如你可以将user-service的实例分为北京集群上海集群,实现地域级别的服务调用。

6. 配置(Config)

配置是 Nacos 中存储的键值对数据,对应应用程序的配置文件。每个配置都有一个唯一的标识:Data ID + Group + Namespace

三、Nacos 核心功能一:服务注册与发现

服务注册与发现是 Nacos 最基础也是最核心的功能。它解决了微服务之间如何相互发现和调用的问题。

3.1 服务注册流程

当一个服务启动时,它会向 Nacos 服务器发送一个注册请求,将自己的服务信息(服务名、IP 地址、端口号、健康状态等)注册到 Nacos 中。

Nacos 收到注册请求后,会将这个服务实例的信息存储到自己的注册表中。同时,Nacos 会向所有订阅了这个服务的客户端推送最新的服务列表。

3.2 心跳机制与健康检查

服务注册到 Nacos 后,需要定期向 Nacos 发送心跳包,证明自己还活着。默认情况下,心跳间隔是 5 秒。

如果 Nacos 在 15 秒内没有收到某个实例的心跳包,就会将这个实例标记为不健康。如果在 30 秒内还没有收到心跳包,就会将这个实例从注册表中删除。

3.3 服务发现流程

当服务 A 需要调用服务 B 时,它会向 Nacos 发送一个服务发现请求,获取服务 B 的所有健康实例列表。

Nacos 会将服务 B 的实例列表返回给服务 A,服务 A 会将这个列表缓存到本地。然后服务 A 会根据负载均衡策略,选择一个实例进行调用。

为了保证服务列表的实时性,服务 A 会定期(默认 30 秒)向 Nacos 拉取最新的服务列表。同时,当服务 B 的实例发生变化时,Nacos 也会主动推送最新的服务列表给服务 A。

四、Nacos 核心功能二:动态配置中心

动态配置中心是 Nacos 另一个非常重要的功能。它解决了微服务架构下配置管理的痛点,实现了配置的统一管理、动态更新和版本控制。

4.1 配置发布与同步流程

  1. 运维人员在 Nacos 管理界面发布或修改配置
  2. Nacos 将配置更新到自己的数据库中
  3. Nacos 向所有订阅了这个配置的客户端推送配置更新通知
  4. 客户端收到通知后,从 Nacos 拉取最新的配置
  5. 客户端更新本地缓存的配置,应用程序使用最新的配置

整个过程不需要重启服务,配置修改后实时生效。

4.2 动态配置刷新原理

Nacos 提供了两种配置刷新方式:

  1. 自动刷新:在@Value注解上加上@RefreshScope注解,当配置发生变化时,会自动刷新字段的值
  2. 监听刷新:通过ConfigService添加配置监听器,当配置发生变化时,会触发监听器的回调方法

自动刷新示例

java

运行

@RestController
@RefreshScope // 开启自动刷新
public class ConfigController {
    @Value("${config.info:默认值}")
    private String configInfo;

    @GetMapping("/config")
    public String getConfigInfo() {
        return configInfo;
    }
}

4.3 配置版本控制与回滚

Nacos 会自动保存配置的历史版本,每次修改配置都会生成一个新的版本号。如果配置修改后出现问题,可以一键回滚到之前的任意版本,非常方便。

五、Spring Boot 整合 Nacos 完整教程

下面我就以 Spring Boot 2.7.x 为例,教你如何快速整合 Nacos 的服务注册发现和配置中心功能。

第一步:引入依赖

xml

<!-- Spring Cloud Alibaba Nacos 服务注册发现 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!-- Spring Cloud Alibaba Nacos 配置中心 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

第二步:配置 Nacos

bootstrap.yml中添加 Nacos 配置(注意:必须是bootstrap.yml,不能是application.yml):

yaml

spring:
  application:
    name: user-service # 服务名称,必须配置
  cloud:
    nacos:
      # 服务注册发现配置
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 服务器地址
        namespace: dev # 命名空间
        group: DEFAULT_GROUP # 分组
      # 配置中心配置
      config:
        server-addr: 127.0.0.1:8848
        namespace: dev
        group: DEFAULT_GROUP
        file-extension: yaml # 配置文件格式
        # 共享配置
        shared-configs:
          - data-id: common-config.yaml
            group: DEFAULT_GROUP
            refresh: true # 开启自动刷新

第三步:开启服务注册发现

在启动类上添加@EnableDiscoveryClient注解:

java

运行

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

现在,你的服务启动后就会自动注册到 Nacos 中了。

第四步:使用 OpenFeign 进行服务调用

Nacos 整合 OpenFeign 非常简单,只需要三步:

  1. 引入 OpenFeign 依赖:

xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在启动类上添加@EnableFeignClients注解:

java

运行

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}
  1. 编写 Feign 接口:

java

运行

@FeignClient(name = "order-service") // 服务名称,对应 Nacos 中的服务名
public interface OrderFeignClient {
    @GetMapping("/order/{userId}")
    List<Order> getOrdersByUserId(@PathVariable Long userId);
}

现在,你就可以在代码中注入这个接口,像调用本地方法一样调用远程服务了:

java

运行

@Service
public class UserService {
    @Autowired
    private OrderFeignClient orderFeignClient;

    public User getUserWithOrders(Long userId) {
        User user = userMapper.selectById(userId);
        // 调用远程服务
        List<Order> orders = orderFeignClient.getOrdersByUserId(userId);
        user.setOrders(orders);
        return user;
    }
}

六、Nacos 高可用集群部署

生产环境中,绝对不能使用单机 Nacos,否则 Nacos 挂了,整个微服务系统都会瘫痪。Nacos 支持集群部署,官方推荐至少部署 3 个节点,组成一个高可用集群。

6.1 Nacos 集群架构

Nacos 集群采用 "一主多从" 的架构,所有节点都是对等的,没有主从之分。客户端可以连接任意一个节点,所有节点之间会自动同步数据。

Nacos 集群依赖 MySQL 数据库来存储配置和服务数据,所有节点都连接同一个 MySQL 数据库(或 MySQL 集群)。

6.2 集群部署步骤

  1. 准备 3 台服务器:192.168.1.10、192.168.1.11、192.168.1.12
  2. 安装 MySQL 数据库:创建数据库nacos,执行 Nacos 提供的 SQL 脚本初始化数据库
  3. 下载 Nacos 安装包:在 3 台服务器上都下载并解压 Nacos
  4. 修改配置文件:修改每台服务器上的conf/application.properties文件,配置数据库连接信息
  5. 配置集群节点:在每台服务器上创建conf/cluster.conf文件,写入所有节点的地址:

    plaintext

    192.168.1.10:8848
    192.168.1.11:8848
    192.168.1.12:8848
    
  6. 启动 Nacos:在每台服务器上执行bin/startup.sh启动 Nacos
  7. 配置负载均衡:在 Nginx 中配置反向代理,将请求转发到 3 个 Nacos 节点上

现在,你就拥有了一个高可用的 Nacos 集群了。客户端只需要配置 Nginx 的地址,就可以访问集群了。

七、生产环境常见坑与最佳实践

坑 1:配置不生效

常见原因

  • 配置文件格式错误
  • Data ID、Group、Namespace 不匹配
  • 没有开启自动刷新
  • 配置优先级问题

解决方案

  • 检查配置文件格式是否正确
  • 确保 Data ID、Group、Namespace 与代码中的配置一致
  • 在需要自动刷新的类上添加@RefreshScope注解
  • 了解 Nacos 配置的优先级规则,避免配置被覆盖

坑 2:服务注册不上

常见原因

  • Nacos 服务器地址配置错误
  • 防火墙或安全组没有开放 8848 端口
  • 服务名称配置错误
  • 网络不通

解决方案

  • 检查 Nacos 服务器地址是否正确
  • 开放 8848 端口和集群通信端口
  • 确保服务名称唯一且正确
  • 测试网络连通性

坑 3:服务调用失败

常见原因

  • 服务提供者没有注册到 Nacos
  • 服务消费者没有获取到最新的服务列表
  • 负载均衡策略配置错误
  • 服务提供者宕机

解决方案

  • 检查服务提供者是否正常注册
  • 检查服务消费者的服务列表是否正确
  • 配置合理的负载均衡策略
  • 开启服务健康检查和自动剔除

坑 4:Nacos 内存溢出

常见原因

  • 服务数量太多,实例数量太大
  • 配置数量太多,历史版本太多
  • JVM 堆内存设置太小

解决方案

  • 合理设置 JVM 堆内存大小,建议至少 2G
  • 定期清理无用的服务和配置
  • 开启配置历史版本自动清理

最佳实践

  1. 使用命名空间隔离环境:开发、测试、生产环境使用不同的命名空间
  2. 使用分组管理项目:同一个项目的所有服务和配置放在同一个分组下
  3. 配置合理的心跳间隔:默认 5 秒,生产环境可以适当调整
  4. 开启配置自动刷新:对于需要动态更新的配置,一定要开启自动刷新
  5. 定期备份配置:定期导出 Nacos 配置,防止数据丢失
  6. 监控 Nacos 状态:监控 Nacos 集群的健康状态、内存使用率、CPU 使用率等指标
  7. 限制配置大小:单个配置文件不要超过 100KB,大配置建议拆分
  8. 不要在配置中存储敏感信息:敏感信息(如数据库密码)应该加密存储
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐