前言
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。这是官方对Nacos的定义,Nacos既可以作为注册中心也可以作为配置中心,同时作为注册中心的时候支持AP和CP两种架构,可以说非常Nice!,这里了我就先对AP模式的实现进行一些探讨,2.X的版本变化较大,本文是基于1.4.X的版本进行探讨。
注册表
谈起来AP就要说到大名鼎鼎的CAP和Base理论,也就是一致性和可用性的取舍,AP就是最近可用性。 首先 AP是通过注册的时候是否临时实例来控制的,默认是临时实例也就是AP。先把注册表的样子给大家看看吧。
注册表实际上就是一个双层Map(Map<namespace, Map<group::serviceName, Service>>)
可以看出结构还是有点复杂的,有了解过Eureka的会知道,Eureka的注册表是由多级缓存组成的,读的 读写的,然后定时同步,这样其实会有所延迟,现在来看看Nacos在1.4.x上是如何实现的。
服务发现客户端
服务发现客户端这边主要有两个比较重要的Task,分别是: com.alibaba.nacos.client.naming.beat.BeatReactor.BeatTask 、 com.alibaba.nacos.client.naming.core.HostReactor.UpdateTask 前者是负责向注册中心发送心跳包,后者则是客户端主动拉取数据,可以理解为数据同步的兜底策略,当然服务端也有主动推送的策略。
服务发现服务端
注册中心的信息推送,是基于UDP,若在规定的次数中都失败了,那么还有上面的客户端发起的数据同步兜底策略,所以这里Nacos比Eureka的实时性高,和zk的那种长连接的方式相比,注册中心的压力不大,性能有了比较大的提升。同时在于注册表的更新上也做了很大的优化,采用了写时复制的思想(COW),先将数据写入一个内存队列,然后通过一个线程不断去消费一个内存队列,采用写时复制的思想,复制注册表出来 然后进行更新后再覆盖上去,这样既保证了性能又保证了注册表的更新。 ClientBeatCheckTask 负责进行心跳检测 注意这里通过计算服务名称来保证执行一个service的心跳检测只在一台机器上执行(需要是健康的实例)
- 若一个实例超过15没有收到心跳,那么将它的健康状况设置为false
- 若超过30秒没有收到心跳,会进行实例的剔除,如果重新收到心跳将会进行重新注册
服务发现 服务端集群通信
集群通信也是采用定时任务的机制进行定期的心跳和信息同步。 这里还存在疑惑,因为有两个地方都有类似的定时任务,不过一个地方已经被标注为过时了。 com.alibaba.nacos.naming.cluster.ServerListManager#init(过时) com.alibaba.nacos.naming.core.ServiceManager#init