当前位置: 首页 > 工具软件 > turn-client > 使用案例 >

Nacos注册中心6-Client端(获取调用服务的提供者列表)

柯立果
2023-12-01

0. 环境

  • nacos版本:1.4.1
  • Spring Cloud : 2020.0.2
  • Spring Boot :2.4.4
  • Spring Cloud alibaba: 2.2.5.RELEASE

测试代码:github.com/hsfxuebao/s…

1. 获取调用服务的提供者列表

请求时机:Client端在调用服务提供者具体方法时,才能调用

public ZoneAwareLoadBalancer(IClientConfig clientConfig, IRule rule,
                             IPing ping, ServerList<T> serverList, ServerListFilter<T> filter,
                             ServerListUpdater serverListUpdater) {
    super(clientConfig, rule, ping, serverList, filter, serverListUpdater);
}

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping,
                                     ServerList<T> serverList, ServerListFilter<T> filter,
                                     ServerListUpdater serverListUpdater) {
    super(clientConfig, rule, ping);
    this.serverListImpl = serverList;
    this.filter = filter;
    this.serverListUpdater = serverListUpdater;
    if (filter instanceof AbstractServerListFilter) {
        ((AbstractServerListFilter) filter).setLoadBalancerStats(getLoadBalancerStats());
    }
    restOfInit(clientConfig);
}

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());
}
com.netflix.loadbalancer.DynamicServerListLoadBalancer#updateListOfServers
@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);
}

com.alibaba.cloud.nacos.ribbon.NacosServerList#getUpdatedListOfServers
@Override
public List<NacosServer> getUpdatedListOfServers() {
   return getServers();
}
private List<NacosServer> getServers() {
   try {
      String group = discoveryProperties.getGroup();
      List<Instance> instances = discoveryProperties.namingServiceInstance()
            .selectInstances(serviceId, group, true);
      return instancesToServerList(instances);
   }
   catch (Exception e) {
      throw new IllegalStateException(
            "Can not get service instances from nacos, serviceId=" + serviceId,
            e);
   }
}
复制代码

com.alibaba.nacos.client.naming.NacosNamingService#selectInstances:

@Override
public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy,
        boolean subscribe) throws NacosException {

    ServiceInfo serviceInfo;
    if (subscribe) {
        // 获取到要调用服务的serviceInfo
        serviceInfo = hostReactor.getServiceInfo(NamingUtils.getGroupedName(serviceName, groupName),
                StringUtils.join(clusters, ","));
    } else {
        serviceInfo = hostReactor
                .getServiceInfoDirectlyFromServer(NamingUtils.getGroupedName(serviceName, groupName),
                        StringUtils.join(clusters, ","));
    }
    // todo 从serviceInfo的所有instance实例中过滤出所有可用的
    return selectInstances(serviceInfo, healthy);
}
复制代码

其中 getServiceInfo方法上一篇Nacos注册中心5-Client端(更新本地服务)中已经信息分析了,我们看一下selectInstances(serviceInfo, healthy)

private List<Instance> selectInstances(ServiceInfo serviceInfo, boolean healthy) {
    List<Instance> list;
    if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
        return new ArrayList<Instance>();
    }

    Iterator<Instance> iterator = list.iterator();
    // 迭代服务的所有instance实例
    while (iterator.hasNext()) {
        Instance instance = iterator.next();
        // 若当前instance不是健康的,或不可用,或其权重小于等于0,则从列表中将其删除
        if (healthy != instance.isHealthy() || !instance.isEnabled() || instance.getWeight() <= 0) {
            iterator.remove();
        }
    }
    // 返回的这个列表中包含的instance都是可用的
    return list;
}
复制代码

2. 方法调用图

参考文章

nacos-1.4.1源码分析(注释)
springcloud-source-study学习github地址
深度解析nacos注册中心
mac系统如何安装nacos

 类似资料: