Nacos注册中心原理

发布于:2025-05-29 ⋅ 阅读:(38) ⋅ 点赞:(0)

一、核心架构图示


二、关键技术流程详解

1. 服务注册阶段

  • 实现原理​:服务启动时将元数据(服务名、实例ID、端点地址)封装成instance对象向注册中心发起POST请求
  • 关键参数​:
# 示例配置(Spring Boot)
spring:
cloud:
inetutils:
preferred-networks: 192.168.1.0/24 # IP过滤规则
instance-id: ${spring.application.name}:${server.port}
1.1 注册存储

在Nacos Server(注册中心)接收到请求后:

1)将服务实例信息持久化到内存数据库(基于Raft协议的nacos/nacos-cluster模块)

2)同步更新到本地文件系统(snapshot机制)

3)构建服务实例索引(按服务名+分组归类)

2. 服务发现阶段

  • 订阅机制​:
  • 长连接:WebSocket保持实时通信
  • 短轮询:HTTP GET /services/{serviceName} 定期拉取
  • 缓存策略​:
// 客户端缓存实现示例
public class ServiceCache {
private Map<String, List<ServiceInstance>> cache = new ConcurrentHashMap<>();

@Scheduled(fixedDelay = 30000)
public void refreshCache() {
cache.putAll(registryClient.getServices());
    }
}

3. 心跳续约机制

服务提供者在注册中心完成注册之后与注册中心会建立长连接:

1)服务实例每5秒发送一次心跳(默认间隔)

2)注册中心通过TCP长连接(默认端口7848)接收心跳

3)心跳超时时间默认15秒,超时实例将被剔除

3.1 如何处理心跳请求?
  • 注册中心接收到服务提供者的心跳请求,接着解析请求中的Instance对象并执行以下核心操作:

        (1) 实例注册校验

        若服务实例不存在:立即异步注册

        若已存在:更新最后心跳时间

        (2) 状态维护

        自动恢复非健康实例为健康状态

        (3) 异步处理

        启动独立线程执行注册/更新操作,避免阻塞主流程

  • 注册中心注册表维护机制

        (1)注册表的数据结构

        使用ConcurrentHashMap分级存储:Map<命名空间, Map<分组:服务名, Service对象>>

        (2)持久化策略

模式 协议 触发条件
CP模式 基于Raft协议
  • 需集群半数以上节点确认写入
  • 数据同步至内存和磁盘
AP模式 基于Distro协议
  • 异步批量同步至其他节点
  • 优先保证可用性

4. 负载均衡策略

以下是 Nacos 客户端(服务调用者)常用的负载均衡策略对比表:

策略名称 核心原理 适用场景 优点 缺点 配置示例
轮询(Round Robin)​ 按顺序依次选择实例(如实例列表为 [A,B,C],依次选择 A→B→C→A...) 实例性能相近的简单场景 实现简单,请求均匀分布 忽略实例实际负载差异 LoadBalancerClient.setRule(new RoundRobinRule())
随机(Random)​ 从实例列表中随机选择一个实例 实例性能差异不大的高并发场景 无状态,实现简单 可能导致某些实例过载 new RandomRule()
加权轮询(Weighted Round Robin)​ 根据实例权重分配请求(权重高的实例被选中概率更高) 实例配置差异明显的场景(如不同规格服务器) 灵活应对实例性能差异 需手动配置权重 new WeightedResponseTimeRule()
最少连接(Least Connections)​ 优先选择当前连接数最少的实例 长连接服务(如数据库、WebSocket) 动态感知实例负载 需维护连接数状态 new LeastConnectionsRule()
响应时间权重(Response Time Weighted)​ 根据实例平均响应时间动态计算权重(响应越快,权重越高) 对延迟敏感的服务调用 自动优化用户体验 需持续监控响应时间 new BestAvailableRule()
一致性哈希(Consistent Hashing)​ 通过哈希环将请求映射到固定实例,相同参数的请求总是路由到同一实例(会话粘滞) 需保持会话状态的服务(如购物车) 避免缓存失效,减少热点问题 实例扩缩容时哈希抖动 new ConsistentHashRule()

​补充说明

  1. 默认策略​:Nacos 默认使用 ​加权轮询​(结合实例健康状态和响应时间动态调整权重)。
  2. 扩展性​:可通过实现 IRule 接口自定义策略(如基于 CPU/内存利用率的动态权重算法)。
  3. 配置方式​:在 Spring Cloud 中可通过 application.yml 配置:
    spring:
      cloud:
        loadbalancer:
          ribbon:
            NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

选择建议​:中小规模服务优先使用默认加权轮询;对延迟敏感场景选择响应时间权重;需要会话粘滞时选一致性哈希。

三、技术选型对比矩阵

特性 Consul Eureka Nacos
协议支持 HTTP/gRPC HTTP HTTP/gRPC
一致性模型 CP AP CP+AP
配置中心 内置 需独立部署 内置
部署复杂度 中等(需etcd) 简单(纯Java) 简单(Spring Cloud集成)

实施建议​:中小规模系统推荐使用Nacos(简化运维),金融级系统建议Consul+Istio组合(强一致性+服务网格)。关键业务系统务必配置健康检查熔断机制,建议心跳超时时间设置为30s-60s,重试次数不超过3次。

四、思考

此时​你的服务提供者其中有一个服务挂掉了,这时候其注册中心和调用者会怎么做呢?

情况一:服务提供者在销毁时间前恢复

1. 服务提供者动作

  • 重启并恢复心跳​:服务提供者进程重启后,重新向 Nacos Server 发送心跳请求(PUT 接口),携带自身实例信息(IP、端口、服务名等)。

2. 注册中心(Nacos Server)动作

  • 接收心跳请求​:Nacos Server 收到心跳后,检查实例状态:
  • 若实例此前被标记为 ​非健康,则将其状态更新为 ​健康
  • 若实例此前已被 ​注销​(超过销毁时间),则忽略此次心跳(视为无效恢复)。
  • 触发健康状态更新事件​:通过 ​UDP 通信​ 向所有订阅该服务的客户端广播服务实例状态变更事件(如 InstanceStatusChangedEvent)。
  • 持久化存储更新​:若启用 CP 模式(Raft 协议),更新 Raft 日志并同步到集群半数以上节点;若为 AP 模式(Distro 协议),异步更新内存并广播增量数据。

3. 调用者动作

  • 接收事件通知​:客户端通过 UDP 监听收到实例状态变更事件(如 InstanceStatusChangedEvent)。

  • 更新本地缓存​:将恢复健康的实例重新加入负载均衡候选池。
  • 后续调用逻辑​:下次发起请求时,负载均衡器(如 Ribbon)会基于最新实例列表选择健康实例(包括刚恢复的实例)。

情况二:服务提供者在销毁时间后恢复

1. 服务提供者动作

  • 超时后重启​:服务提供者因宕机超过销毁时间(如 Nacos 配置的 ephemeralTTL 或默认 30 秒),实例已被注册中心移除。
  • 重新注册​:进程重启后,向 Nacos Server 发送 ​POST 请求​ 触发全新注册(而非恢复旧实例)。

2. 注册中心(Nacos Server)动作

  • 处理新注册请求​:
  • 将实例信息封装为新的 Instance 对象。
  • 创建异步任务写入注册表(CP 模式需 Raft 半数节点确认,AP 模式直接写入内存并向集群广播)。
  • 推送全量服务列表​:通过 ​UDP 向客户端(调用者)广播服务实例变更事件​(如 ServiceChangeEvent),通知所有订阅者该服务实例已重新加入集群。

3. 调用者动作

  • 接收全量更新事件​:客户端收到事件后,触发 ​本地缓存刷新​(通过定时拉取或 UDP 事件驱动)。
  • 移除旧实例​:本地缓存中已不存在超时的旧实例,新注册的实例作为独立实体加入服务列表。
  • 负载均衡调整​:后续调用会基于最新服务列表(包含新注册实例)进行路由。

网站公告

今日签到

点亮在社区的每一天
去签到