Service 实现了 RecordListener 接口,在 service 的 instance 发生变化时,调用 onChange 方法。
nacos 在创建 service 对象的时候,会把 service 放入 DistroConsistencyServiceImpl#listeners 中(这里只考虑服务的临时实例)
// com.alibaba.nacos.naming.core.ServiceManager#putServiceAndInit private void putServiceAndInit(Service service) throws NacosException { putService(service); service.init(); consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service); consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service); Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON()); }
当 service 有新的实例注册时
1. 修改内存中的数据,推送服务实例变化给 nacos 客户端
Notifier 增加 Task
// com.alibaba.nacos.naming.consistency.ephemeral.distro.DistroConsistencyServiceImpl#onPut public void onPut(String key, Record value) { // 更新 Datum if (KeyBuilder.matchEphemeralInstanceListKey(key)) { Datum<Instances> datum = new Datum<>(); datum.value = (Instances) value; datum.key = key; datum.timestamp.incrementAndGet(); dataStore.put(key, datum); } if (!listeners.containsKey(key)) { return; } // 创建 task 放入队列 notifier.addTask(key, ApplyAction.CHANGE); }
从队列取出任务执行,触发 Service.onChange
// com.alibaba.nacos.naming.core.Service#onChange
1.1 更新 Service 对象的内容
1.2 推送变化给 udp 客户端
// com.alibaba.nacos.naming.push.PushService#serviceChanged public void serviceChanged(Service service) { // merge some change events to reduce the push frequency: if (futureMap.containsKey(UtilsAndCommons.assembleFullServiceName(service.getNamespaceId(), service.getName()))) { return; } this.applicationContext.publishEvent(new ServiceChangeEvent(this, service)); } // com.alibaba.nacos.naming.push.PushService#onApplicationEvent
客户端在查询服务实例的时候,如果提供 udp 端口,则 server 会创建 udpClient,当服务实例发生变化时,推送更新
// com.alibaba.nacos.naming.push.PushService#addClient
2. 当前 nacos 要同步数据给其他 nacos 节点
// com.alibaba.nacos.naming.consistency.ephemeral.distro.DataSyncer#submit // com.alibaba.nacos.naming.misc.NamingProxy#syncData
URL 是 /v1/ns/distro/datum
处理请求是 DistroController#onSyncDatum
3. nacos 节点之间还有一种定时同步数据的方式
// com.alibaba.nacos.naming.consistency.ephemeral.distro.DataSyncer.TimedSync
当前 nacos 节点把自己负责的 service 的 key 和实例的 md5 签名发送给其他 nacos 节点
所以会有多个 nacos 节点推送 udp 报文给同一个客户端吗?
原文:https://www.cnblogs.com/allenwas3/p/12115863.html