服务发现

目录

TIP

实例是如何得知其他实例的信息呢?毕竟需要远程调用嘛

两种方式:1.客户端主动获取(定时更新)、2.服务端主动推送(长连接推送变更信息)

客户端主动获取

客户端

1.入口

NacosNamingService.getAllInstances

该方法就是获取所需的服务信息

2.第一次获取

HostReactor.getServiceInfo

1.先是故障转移机制判断是否去本地文件中读取信息,读到则返回

2.再去本地服务列表读取信息(本地缓存),没读到则创建一个空的服务,然后立刻去nacos中读取更新

3.读到了就返回,同时开启定时更新,定时向服务端同步信息 (正常1s,异常最多60s一次)

HostReactor.updateServiceNow

HostReactor.updateService

属性的serverProxy,这里面就是接口调用请求了

3.定时延迟任务

HostReactor.scheduleUpdateIfAbsent

这里全先判断定时任务是否已经在异步任务列表中了,不在才会添加一个UpdateTask任务延迟执行

UpdateTask.run

UpdateTask类就是一个异步执行类,里面会调用updateService方法更新服务信息,同时结束又会开启延迟,延迟的时间跟请求失败的次数有关,最多60s,正常是1s一次

无论是updateService方法、refreshOnly方法,还是刚开始的直接去nacos拉取信息的方法都会调用serverProxy.queryList方法,这个方法就是HTTP请求获取信息:

获取服务信息列表URL:/nacos/v1/ns/instance/list

NamingProxy.queryList

服务端

InstanceController.list()

服务端这边处理请求就比较简单了,除去参数获取以及相关校验就剩服务列表的获取了

InstanceController.doSrvIpxt如下:

这里记住有个PushService

服务端主动推送

既然是主动推送那么就需要两个条件:1.建立长连接2.触发推送的事件

服务端

上面InstanceController.doSrvIpxt中的pushService.addClient就是把客户端UDP、IP等信息封装成PushClient对象存储在PushService类中,方便以后服务变更后推送消息

PushService类实现ApplicationListener接口,监听ServiceChangeEvent(服务变更事件)

ServiceChangeEvent事件处理就在当前类下:

事件触发则是PushService.serviceChanged方法,这个方法之前我们就见过,在服务注册里面,心跳里面也有,服务变更就会调用这个方法,触发事件让服务端主动推送服务变更信息

客户端

客户端是在PushReceiver类里面,这个类是个Runnable会在HostReactor中被实例化

PushReceiver.run()

收到服务端的信息就会交给HostReactor.processServiceJson处理

HostReactor.processServiceJson就会更新本地缓存的信息,上述客户端主动拉取的时候也会调用这个方法更新

HostReactor.processServiceJson

中间一大段省略了哈,最重要的就是那几步:

  1. 更新本地缓存
  2. 发布实例变更事件
  3. 写入磁盘(故障转移机制)

总结

服务的发现有两种方式

客户端主动获取

  • 会先读取缓存,缓存内读取不到则会去服务端获取,同时开启一个定时任务定时更新
  • 定时任务1s一次,异常时会延长时间最长60s
  • 拉取URL:/nacos/v1/ns/instance/list

服务端主动推送

  • 服务端和客户端在启动后会建立一个长连接
  • 服务端服务变更后会发布服务变更事件ServiceChangeEvent,会通过长连接将变更后的信息发送给客户端
  • 客户端更新的方式是hostReactor.processServiceJson方法会写入缓存、发布实例变更事件、写入磁盘
Last Updated: