前面已经看完Nacos的服务注册,服务发现,接下来就得看服务调用了。默认的微服务调用负载均衡是由Ribbon实现的,在为调用的微服务创建独立的应用上下文时来发现微服务,就从这里开始看。首先需要实例化负载均衡器ILoadBalancer,默认是ZoneAwareLoadBalancer实现,此时会调用DynamicServerListLoadBalancer.java类中的restOfInit()方法获取Nacos维护的微服务。
void restOfInit(IClientConfig clientConfig) {
boolean primeConnection = this.isEnablePrimingConnections();
// turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()
this.setEnablePrimingConnections(false);
// 开个任务定时获取微服务
enableAndInitLearnNewServersFeature();
// 初始化时立即获取一次微服务
updateListOfServers();
if (primeConnection && this.getPrimeConnections() != null) {
this.getPrimeConnections()
.primeConnections(getReachableServers());
}
this.setEnablePrimingConnections(primeConnection);
LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
}
其实就是通过serverListImpl(ServerList)发现微服务,如果使用了Nacos则使用NacosServerList,因此就是通过这个类来实现的,最后还是由NacosNamingService.java类的selectInstances()方法来发现微服务的。Nacos是在定时任务里获取服务端的微服务的,然后缓存在serviceInfoMapprivate Map<String, ServiceInfo> serviceInfoMap;
中,key是微服务名,value是ServiceInfo,此时就能将获取到的微服务传到Ribbon。
public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy, boolean subscribe) throws NacosException {
ServiceInfo serviceInfo;
if (subscribe) {
serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","));
} else {
serviceInfo = hostReactor.getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","));
}
return selectInstances(serviceInfo, healthy);
}
再就是通过serverListUpdater调度定时任务周期性刷新微服务,还是通过Nacos的NacosServerList获取微服务,而Nacos会定期刷新微服务,这个前面已经讲过Nacos服务发现源码解析。
@VisibleForTesting
public void updateListOfServers() {
List<T> servers = new ArrayList<T>();
if (serverListImpl != null) {
servers = serverListImpl.getUpdatedListOfServers();
LOGGER.debug("List of Servers for {} obtained from Discovery client: {}",
getIdentifier(), servers);
if (filter != null) {
servers = filter.getFilteredListOfServers(servers);
LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}",
getIdentifier(), servers);
}
}
updateAllServerList(servers);
}
Ribbon获取到微服务后就是通过RestTemplate来调用的,这个前面也已经说过Ribbon调用过程。
总结一下,Ribbon通过Nacos的NacosServerList来获取微服务,并且开启任务周期性刷新微服务。