Nacos源码解析系列目录
- Nacos 源码编译运行
- (Nacos源码解析一)Nacos 注册实例源码解析
- (Nacos源码解析二)Nacos 服务发现源码解析
- (Nacos源码解析三)Nacos 心跳机制源码解析
- (Nacos源码解析四)Nacos服务健康检查源码解析
- (Nacos源码解析五)Nacos服务事件变动源码解析
Nacos服务事件变动源码解析
概念
当客户端向服务端注册服务或发送心跳的时候,服务端会推送服务时间变动事件,通过udp协议向客户端通知
1、客户端注册事件变动
下面的源码流程为注册的实例数据从阻塞队列中取出并更新到了cluster的ephemeralInstances 属性最后会发布服务变动事件,Nacos注册源码解析见
(Nacos源码解析一)Nacos 注册实例源码解析
com.alibaba.nacos.naming.consistency.ephemeral.distro.DistroConsistencyServiceImpl.Notifier#run
com.alibaba.nacos.naming.consistency.ephemeral.distro.DistroConsistencyServiceImpl.Notifier#handle
com.alibaba.nacos.naming.core.Service#onChange
com.alibaba.nacos.naming.core.Service#updateIPs
public void updateIPs(Collection<Instance> instances, boolean ephemeral) {
...
// 发布事件
getPushService().serviceChanged(this);
...
}
2、客户端心跳机制事件变动
下面的源码流程为处理客户端发送的心跳请求,开启一个定时任务,更新实例的最后心跳时间,最后发布服务变动事件,Nacos心跳机制见
(Nacos源码解析三)Nacos 心跳机制源码解析
com.alibaba.nacos.naming.controllers.InstanceController#beat
com.alibaba.nacos.naming.core.Service#processClientBeat
com.alibaba.nacos.naming.healthcheck.ClientBeatProcessor#run
@Override
public void run() {
Service service = this.service;
if (Loggers.EVT_LOG.isDebugEnabled()) {
Loggers.EVT_LOG.debug("[CLIENT-BEAT] processing beat: {}", rsInfo.toString());
}
String ip = rsInfo.getIp();
String clusterName = rsInfo.getCluster();
int port = rsInfo.getPort();
// 获取集群
Cluster cluster = service.getClusterMap().get(clusterName);
// 获取集群下全部实例
List<Instance> instances = cluster.allIPs(true);
for (Instance instance : instances) {
if (instance.getIp().equals(ip) && instance.getPort() == port) {
if (Loggers.EVT_LOG.isDebugEnabled()) {
Loggers.EVT_LOG.debug("[CLIENT-BEAT] refresh beat: {}", rsInfo.toString());
}
// 更新最后心跳时间
instance.setLastBeat(System.currentTimeMillis());
if (!instance.isMarked()) {
if (!instance.isHealthy()) {
instance.setHealthy(true);
Loggers.EVT_LOG
.info("service: {} {POS} {IP-ENABLED} valid: {}:{}@{}, region: {}, msg: client beat ok",
cluster.getService().getName(), ip, port, cluster.getName(),
UtilsAndCommons.LOCALHOST_SITE);
// 发布服务变动事件
getPushService().serviceChanged(service);
}
}
}
}
}
3、Spring发布服务变更事件
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));
}
4、处理服务变更事件,通过udp协议向客户端推送变更数据
com.alibaba.nacos.naming.push.PushService#onApplicationEvent
@Override
public void onApplicationEvent(ServiceChangeEvent event) {
Service service = event.getService();
String serviceName = service.getName();
String namespaceId = service.getNamespaceId();
...
// 封装信息
// 向客户端推送变更的信息
udpPush(ackEntry);
...
}
com.alibaba.nacos.naming.push.PushService#udpPush