服务发现就是查询实例列表。
客户端服务发现的入口在
com.alibaba.nacos.client.naming.NacosNamingService#getAllInstances(java.lang.String, java.lang.String, java.util.List, boolean)
--> com.alibaba.nacos.client.naming.core.HostReactor#getServiceInfo
getServiceInfo0
首先会通过getServiceInfo0方法,从缓存中获取数据。 serviceInfoMap就是本地的缓存。
private ServiceInfo getServiceInfo0(String serviceName, String clusters) {String key = ServiceInfo.getKey(serviceName, clusters);return serviceInfoMap.get(key);
}
updateService
首次进入可能是获取不到的,所以这里就会调用updateServiceNow方法进行更新服务列表。
com.alibaba.nacos.client.naming.core.HostReactor#updateServiceNow
--> com.alibaba.nacos.client.naming.core.HostReactor#updateService
先通过queryList去服务端获取实例列表
com.alibaba.nacos.client.naming.net.NamingProxy#queryList
reqApi(UtilAndComs.nacosUrlBase + "/instance/list", params, HttpMethod.GET);
如果获取的列表部位空,则调用processServiceJson进行解析。然后存入缓存。
serviceInfoMap.put(serviceInfo.getKey(), serviceInfo);
scheduleUpdateIfAbsent
在getServiceInfo的底部,有一个定时任务的方法,会定时从服务端拉取最新的服务列表,更新到缓存。
com.alibaba.nacos.client.naming.core.HostReactor#scheduleUpdateIfAbsent
addTask(new UpdateTask(serviceName, clusters));
在scheduleUpdateIfAbsent方法中,添加了一个UpdateTask的定时任务。定时任务的执行就是在run方法里。我们来下这个定时任务干了什么。
com.alibaba.nacos.client.naming.core.HostReactor.UpdateTask#run
这里的核心还是调用上面的updateService方法,从服务端获取最新的列表更新到缓存。 然后再finally中递归的调用定时任务,实现了轮询。
客户端的实现比较简单,我们在来看下服务端。
我们看到客户端调用的地址是/nacos/v1/ns/instance/list
reqApi(UtilAndComs.nacosUrlBase + "/instance/list", params, HttpMethod.GET);
对应服务端的接口在com.alibaba.nacos.naming.controllers.InstanceController#list
-->com.alibaba.nacos.naming.controllers.InstanceController#doSrvIpxt
先通过serviceManager.getService从缓存中拿到service,然后
-->service.srvIPs -->com.alibaba.nacos.naming.core.Service#srvIPs
-->allIPs
-->clusterObj.allIPs()
这里就是服务注册的时候注册的实例列表了。
OK,服务端的服务发现更简单,到此为止!