通过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(); ............................... // 获取服务对应的实例列表 ListsrvedIps = 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 ListsrvIPs(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 ListallIPs() { List allInstances = new ArrayList<>(); allInstances.addAll(persistentInstances); allInstances.addAll(ephemeralInstances); return allInstances; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)