服务端解决实例列表申请的入口是InstanceController#list。

InstanceController#list

public ObjectNode list(HttpServletRequest request) throws Exception {            // 其余略    // 获取服务列表    return doSrvIpxt(namespaceId, serviceName, agent, clusters, clientIP, udpPort, env, isCheck, app, tenant,            healthyOnly);}

InstanceController#doSrvIpxt

这里次要是推送UDP申请,退出Client,Nacos - 服务端解决心跳申请的clients就是这里退出的。
另外就是判断爱护阈值,如果比例低于阈值,则把衰弱和不衰弱的都返回,如果高于阈值,就只返回衰弱的实例。

public ObjectNode doSrvIpxt(String namespaceId, String serviceName, String agent, String clusters, String clientIP,            int udpPort, String env, boolean isCheck, String app, String tid, boolean healthyOnly) throws Exception {            ClientInfo clientInfo = new ClientInfo(agent);    ObjectNode result = JacksonUtils.createEmptyJsonNode();    // 从serviceMap缓存获取Service    Service service = serviceManager.getService(namespaceId, serviceName);    long cacheMillis = switchDomain.getDefaultCacheMillis();        // now try to enable the push    try {        // 端口大于0,且客户端agent信息合乎则发表        if (udpPort > 0 && pushService.canEnablePush(agent)) {            // 心跳那个章节的client就是这里加的            pushService                    .addClient(namespaceId, serviceName, clusters, agent, new InetSocketAddress(clientIP, udpPort),                            pushDataSource, tid, app);            cacheMillis = switchDomain.getPushCacheMillis(serviceName);        }    } catch (Exception e) {        Loggers.SRV_LOG                .error("[NACOS-API] failed to added push client {}, {}:{}", clientInfo, clientIP, udpPort, e);        cacheMillis = switchDomain.getDefaultCacheMillis();    }    // 为空封装返回    if (service == null) {        if (Loggers.SRV_LOG.isDebugEnabled()) {            Loggers.SRV_LOG.debug("no instance to serve for service: {}", serviceName);        }        result.put("name", serviceName);        result.put("clusters", clusters);        result.put("cacheMillis", cacheMillis);        result.replace("hosts", JacksonUtils.createEmptyArrayNode());        return result;    }    // 查看service状态    checkIfDisabled(service);        List<Instance> srvedIPs;    // 获取相干实例的ip    srvedIPs = service.srvIPs(Arrays.asList(StringUtils.split(clusters, ",")));        // filter ips using selector:    // 对ip过滤    if (service.getSelector() != null && StringUtils.isNotBlank(clientIP)) {        srvedIPs = service.getSelector().select(clientIP, srvedIPs);    }    // id为空封装返回    if (CollectionUtils.isEmpty(srvedIPs)) {                if (Loggers.SRV_LOG.isDebugEnabled()) {            Loggers.SRV_LOG.debug("no instance to serve for service: {}", serviceName);        }                if (clientInfo.type == ClientInfo.ClientType.JAVA                && clientInfo.version.compareTo(VersionUtil.parseVersion("1.0.0")) >= 0) {            result.put("dom", serviceName);        } else {            result.put("dom", NamingUtils.getServiceName(serviceName));        }                result.put("name", serviceName);        result.put("cacheMillis", cacheMillis);        result.put("lastRefTime", System.currentTimeMillis());        result.put("checksum", service.getChecksum());        result.put("useSpecifiedURL", false);        result.put("clusters", clusters);        result.put("env", env);        result.set("hosts", JacksonUtils.createEmptyArrayNode());        result.set("metadata", JacksonUtils.transferToJsonNode(service.getMetadata()));        return result;    }    // 次要是把衰弱和不衰弱的辨别进去    Map<Boolean, List<Instance>> ipMap = new HashMap<>(2);    ipMap.put(Boolean.TRUE, new ArrayList<>());    ipMap.put(Boolean.FALSE, new ArrayList<>());    for (Instance ip : srvedIPs) {        ipMap.get(ip.isHealthy()).add(ip);    }        if (isCheck) {        result.put("reachProtectThreshold", false);    }        double threshold = service.getProtectThreshold();    // 阈值爱护,衰弱实例和吧衰弱实例的比例小于阈值,则把衰弱和不衰弱的都返回    if ((float) ipMap.get(Boolean.TRUE).size() / srvedIPs.size() <= threshold) {                Loggers.SRV_LOG.warn("protect threshold reached, return all ips, service: {}", serviceName);        if (isCheck) {            result.put("reachProtectThreshold", true);        }                ipMap.get(Boolean.TRUE).addAll(ipMap.get(Boolean.FALSE));        ipMap.get(Boolean.FALSE).clear();    }        // 其余略,就是解决ipMap的信息返回值    return result;}

总结

流程图如下: