NACOS
Server端:
- 集群AP模式: distro协议
- 集群CP模式:raft协议
- 数据同步机制:
1.修改达到一定数量。
2.间隔时间达到标准间隔
注册接口:
InstanceController.register
=》InstanceOperatorClientImpl.registerInstance(namespaceId, serviceName, instance);
=》InstanceOperatorClientImpl.getService //构建一个Service对象
=》ClientOperationServiceProxy.registerInstance//开启注册
=》ClientOperationServiceProxy.chooseClientOperationService//根据实例不同采用不同的注册器
=》临时实例:EphemeralClientOperationServiceImpl
=》ServiceManager.getSingleton //获取或创建
=》getPublishInfo//注入其余信息
=》clientManager.addServiceInstance//将相关信息注入管理器中
=》发布相关事件
=》1.ClientOperationEvent.ClientRegisterServiceEvent//注入信息至这ClientServiceIndexesManager.publisherIndexes
=>1.1 ServiceEvent.ServiceChangedEvent/更新时间版本
=》2.MetadataEvent.InstanceMetadataEvent//设置超时信息
=》持久化实例:PersistentClientOperationServiceImpl
=》ServiceManager.getSingleton //获取或创建
=》WriteRequest生成文件流
=》protocol.write(writeRequest) 持久化到硬盘
=》发布TraceEvent事件(包括注册、注销等)。在相关源码中未发现其实现,查询官网猜测其为轨迹追踪,后续作为插件使用(https://nacos.io/docs/v2/plugin/trace-plugin/)
心跳续期:
InstanceOperatorClientImpl.handleBeat //业务实现类
=》InstanceOperatorClientImpl.getService 获取对应信息
=》//如检测到无注册但存在心跳信息能够生成RsInfo(key=beat),默认为Fasle不添加该参数,注:该参数修改需server段4返回lightBeatEnabled参数才会进行修改<switchDomain>, 会在这帮忙注册 BeatInfoInstanceBuilder
=》通过线程调用ClientBeatProcessorV2.run 刷新健康状态,设置最后时间。发布事件1. 更新时间及版本2.Distro同步3.TraceEvent事件
心跳及健康检测:
ClientBeatCheckTaskV2.doHealthCheck()//IpPortBasedClient.init方法调用时初始化 临时节点默认5秒1次
HealthCheckReactor.doHealthCheck()//IpPortBasedClient.init方法调用时初始化 initCheckRT 校验控制延迟时间2-5秒
IpPortBasedClient.init在注册时调用createIpPortClientIfAbsent一路到底
- 三元分割:NameSpace#GroupId#dataId
- 注册表双层map:结构 Map<NameSpace,Mapgroup::serviceName,ServerInfo> registerList=new concurrentHashMap ServerInfo包含List< host >
Client端:
默认临时节点
手动注册发现核心API
NacosFactory.createNamingService(${nacosServiceAddr})
NamingService.registerInstance(${serviceName},${localhost},${port});=>进行注册
=>封装请求 reqAPI()方法 /instance接口
NamingService.getAllInstances();=>获取服务列表
=>封装请求 reqAPI()方法 /list接口
自动配置:
NacosDiscoveryAutoConfiguration.nacosServiceDiscovery().=>服务注册属性
=》NacosServiceDiscovery.NacosServiceDiscovery() /配置文件交由NamingService处理
=》NacosServiceManager.getNamingService() //建立NamingService
=》NacosServiceManager.buildNamingService //双层检测锁 Double Check Lock 保证线程安全以及单例
=》NacosServiceManager.createNewNamingService //通知NacosFactory创建NamingService
=》NacosFactory.createNamingService//转交给NamingFactory处理
=》NamingFactory.createNamingService.//通过反射进行初始化
=》NacosNamingService.init//初始化方法
=》检测NameSpace参数
=》初始化Serialization 暂不确定其作用疑似注册序列化选择器
=》初始化serverAddr以及EndPoint
=》初始化Web上下文(接口匹配)
=》初始化缓存文件目录=》System.getProperty("user.home")+/nocos/naming/${namespace}
=》初始化日志文件
=》开启事件监听
=》NamingProxy()//SecurityProxy()与Nacos登录相关 采用NamingHttpClientManager作为HttpClient管理工具(双层检测锁 Double Check Lock 生成)
=》NamingProxy.initRefreshTask //多个定时线程进行登录及一个不知道做啥的方法
=》SecurityProxy.login登录获取accessToken 以及tokenTtl(nacosRestTemplate.postForm)
=》new BeatReactor()设置心跳线程池 数量设置 1/2核心数 单核1个
=》run()封装心跳包并发送
=》this.hostReactor() 设置投票线程池 数量设置 1/2核心数 单核1个
=》run() 更新信息 通过UDP协议接收Server包
=》HostReactor.processServiceJson()进行新增或更新ServiceInfo信息
自动注册
第一条 第二次注册,如非临时节点在此修改节点信息与心跳信息包
NacosServiceRegistryAutoConfiguration.NacosAutoServiceRegistration=》初始化注册bean
=》NacosAutoServiceRegistration.super()//提交给父类 AbstractAutoServiceRegistration 处理
=》AbstractAutoServiceRegistration()注入相关信息 同时实现ApplicationListener<WebServerInitializedEvent> 开启事件监听
=》AbstractAutoServiceRegistration.onApplicationEvent() 监听WebServerInitializedEvent 服务器初始化完成发布的事件
=》AbstractAutoServiceRegistration.bind 执行方法
=》AbstractAutoServiceRegistration.start 方法
=》1.发布注册事件
=》2.调用register方法
=》3.再次发布注册事件
=》NacosServiceRegistry.register
=》NacosNamingService.registerInstance
=》registerInstance=》NamingProxy.registerService =》NamingProxy.reqApi=》NamingProxy.callServer=》NacosRestTemplate.exchangeForm()正式发送注册请求
第二条
发送心跳包后响应码是RESOURCE_NOT_FOUND(20404)同时进行注册 初始注册
/*****************************************初始化流程结束***********************************************/
1.设计亮点:采用定时线程替换调度器。1.优化动态时间间隔。2.避免网络延期导致请求堆积。3.Eruka采用多级缓存处理高并发拉取服务列表(短暂延迟更高并发),nacos通过copyOnWrite处理