Spring Cloud Alibaba Nacos 获取服务实例源码分析 instancelist

Spring Cloud Alibaba Nacos 获取服务实例源码分析 instancelist,第1张

Spring Cloud Alibaba Nacos 获取服务实例源码分析 /instance/list

通过Nacos Service提供的服务发现接口:

curl -X GET "http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=sca-provider"

 

{
    "name":"DEFAULT_GROUP@@sca-provider",
    "groupName":"DEFAULT_GROUP",
    "clusters":"",
    "cacheMillis":10000,
    "hosts":[
        {
            "instanceId":"10.244.0.18#18080#DEFAULT#DEFAULT_GROUP@@sca-provider",
            "ip":"10.244.0.18",
            "port":18080,
            "weight":1,
            "healthy":true,
            "enabled":true,
            "ephemeral":true,
            "clusterName":"DEFAULT",
            "serviceName":"DEFAULT_GROUP@@sca-provider",
            "metadata":{
                "dubbo.metadata-service.urls":"[ "dubbo://10.244.0.18:20880/com.alibaba.cloud.dubbo.service.DubbometadataService?anyhost=true&application=sca-provider&bind.ip=10.244.0.18&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=sca-provider&interface=com.alibaba.cloud.dubbo.service.DubbometadataService&methods=getAllServiceKeys,getServiceRestmetadata,getExportedURLs,getAllExportedURLs&pid=8548&qos.enable=false&release=2.7.6&revision=2.2.1.RELEASE&side=provider×tamp=1642390851245&version=1.0.0" ]",
                "preserved.register.source":"SPRING_CLOUD",
                "dubbo.protocols.dubbo.port":"20880"
            },
            "ipDeleteTimeout":30000,
            "instanceHeartBeatTimeOut":15000,
            "instanceHeartBeatInterval":5000
        }
    ],
    "lastRefTime":1642391370735,
    "checksum":"",
    "allIPs":false,
    "reachProtectionThreshold":false,
    "valid":true
}

先说整体思路:

1.根据namespaceId、serviceName获得Service实例
2.从Service实例中基于srvIPs得到所有服务提供者的实例信息
3.遍历组装JSON字符串返回

一、接口 com.alibaba.nacos.naming.controllers.InstanceController#list

    @GetMapping("/list")
    @Secured(parser = NamingResourceParser.class, action = ActionTypes.READ)
    public Object list(HttpServletRequest request) throws Exception {
        
        String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
        String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
        NamingUtils.checkServiceNameFormat(serviceName);
        
       .........................................
// 调用服务com.alibaba.nacos.naming.core.InstanceOperatorServiceImpl#listInstance
        return getInstanceOperator().listInstance(namespaceId, serviceName, subscriber, clusters, healthyOnly);
    }

二、获取实例信息

根据namespaceId和serviceName获取双层Map中的Service服务实例

再把Service中的实例列表转换成集合直接返回

@Override
    public ServiceInfo listInstance(String namespaceId, String serviceName, Subscriber subscriber, String cluster,
            boolean healthOnly) throws Exception {
      
        ServiceInfo result = new ServiceInfo(serviceName, cluster);
        // 根据namespaceId和serviceName(spring.application.name)从双层map中获取服务实例
        Service service = serviceManager.getService(namespaceId, serviceName);
        long cacheMillis = switchDomain.getDefaultCacheMillis();
   
       ...............................
        //  获取服务对应的实例列表    
        List srvedIps = service
                .srvIPs(Arrays.asList(StringUtils.split(cluster, StringUtils.COMMA)));
        
      ..............
    // 把实例信息按健康状态分组放到ipMap 
        long total = 0;
        Map> ipMap = new HashMap<>(2);
        ipMap.put(Boolean.TRUE, new ArrayList<>());
        ipMap.put(Boolean.FALSE, new ArrayList<>());
        
        for (com.alibaba.nacos.naming.core.Instance ip : srvedIps) {
            // remove disabled instance:
            if (!ip.isEnabled()) {
                continue;
            }
            ipMap.get(ip.isHealthy()).add(ip);
            total += 1;
        }
        
        double threshold = service.getProtectThreshold();
// 将ipMap中的实例扔到hosts集合中,有两种情况
// 1.健康的实例数量低于阈值,则直接按所有实例设置healthy=true
// 2.否则直接扔到hosts集合中
// setReachProtectionThreshold 是否到达保护阈值,会根据两种情况设置

        List hosts;
        if ((float) ipMap.get(Boolean.TRUE).size() / total <= threshold) {
            
            Loggers.SRV_LOG.warn("protect threshold reached, return all ips, service: {}", result.getName());
            result.setReachProtectionThreshold(true);
            hosts = Stream.of(Boolean.TRUE, Boolean.FALSE).map(ipMap::get).flatMap(Collection::stream)
                    .map(InstanceUtil::deepCopy)
                    // set all to `healthy` state to protect
                    .peek(instance -> instance.setHealthy(true)).collect(Collectors.toCollection(linkedList::new));
        } else {
            result.setReachProtectionThreshold(false);
            hosts = new linkedList<>(ipMap.get(Boolean.TRUE));
            if (!healthOnly) {
                hosts.addAll(ipMap.get(Boolean.FALSE));
            }
        }
        
        result.setHosts(hosts);
        result.setCacheMillis(cacheMillis);
        result.setLastRefTime(System.currentTimeMillis());
        result.setChecksum(service.getChecksum());
        return result;
    }

三、通过Service获取实例列表的核心方法 com.alibaba.nacos.naming.core.Service#srvIPs

获取集群clusterMap中包含临时和永久的所有实例

public List srvIPs(List clusters) {
        if (CollectionUtils.isEmpty(clusters)) {
            clusters = new ArrayList<>();
            clusters.addAll(clusterMap.keySet());
        }
        return allIPs(clusters);
    }
 
    public List allIPs(List clusters) {
        List result = new ArrayList<>();
        for (String cluster : clusters) {
            Cluster clusterObj = clusterMap.get(cluster);
            if (clusterObj == null) {
                continue;
            }
            
            result.addAll(clusterObj.allIPs());
        }
        return result;
    }

四、从Cluster获取临时和永久的实例

com.alibaba.nacos.naming.core.Cluster#allIPs()

 
    public List allIPs() {
        List allInstances = new ArrayList<>();
        allInstances.addAll(persistentInstances);
        allInstances.addAll(ephemeralInstances);
        return allInstances;
    }

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5705147.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存