nacos服务注册和服务发现源码解析

1、nacos服务注册

1.1、spring cloud nacos服务注册

1. com.alibaba.cloud.nacos.NacosDiscoveryAutoConfiguration在spring-cloud-alibaba-nacos-discovery的META-INF的spring.factories中增加了spi扩展点
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.alibaba.cloud.nacos.NacosDiscoveryAutoConfiguration
  ...
2. 到com.alibaba.cloud.nacos.NacosDiscoveryAutoConfiguration的代码中去看,发现它声明了一个bean。
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
    NacosServiceRegistry registry,
    AutoServiceRegistrationProperties autoServiceRegistrationProperties,
    NacosRegistration registration) {
    return new NacosAutoServiceRegistration(registry,
                                            autoServiceRegistrationProperties, registration);
}
3. 查看com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration的源代码,它继承org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistrationAbstractAutoServiceRegistration实现了ApplicationListener<WebServerInitializedEvent>的接口。顾名思义WebServerInitializedEvent是web容器初始化后发布的事件,看它的实现。
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
    bind(event);
}

当容器初始化后执行bind(WebServerInitializedEvent event)方法

看bing的方法的实现:

public void bind(WebServerInitializedEvent event) {
		ApplicationContext context = event.getApplicationContext();
		if (context instanceof ConfigurableWebServerApplicationContext) {
			if ("management".equals(((ConfigurableWebServerApplicationContext) context)
					.getServerNamespace())) {
				return;
			}
		}
		this.port.compareAndSet(0, event.getWebServer().getPort());
		this.start();
	}

bind方法调用start()方法

start()方法

public void start() {
		if (!isEnabled()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Discovery Lifecycle disabled. Not starting");
			}
			return;
		}

		// only initialize if nonSecurePort is greater than 0 and it isn't already running
		// because of containerPortInitializer below
		if (!this.running.get()) {
			this.context.publishEvent(
					new InstancePreRegisteredEvent(this, getRegistration()));
			register();
			if (shouldRegisterManagement()) {
				registerManagement();
			}
			this.context.publishEvent(
					new InstanceRegisteredEvent<>(this, getConfiguration()));
			this.running.compareAndSet(false, true);
		}

	}

start方法调用register()方法

register()方法

protected void register() {
    this.serviceRegistry.register(getRegistration());
}

结合第2部的代码看,这里的serviceRegistry就是NacosServiceRegistry的实例。

4. 那我们看com.alibaba.cloud.nacos.registry.NacosServiceRegistry#register的代码,
public void register(Registration registration) {

    if (StringUtils.isEmpty(registration.getServiceId())) {
        log.warn("No service to register for nacos client...");
        return;
    }

    String serviceId = registration.getServiceId();

    Instance instance = getNacosInstanceFromRegistration(registration);

    try {
        namingService.registerInstance(serviceId, instance);
        log.info("nacos registry, {} {}:{} register finished", serviceId,
                 instance.getIp(), instance.getPort());
    }
    catch (Exception e) {
        log.error("nacos registry, {} register failed...{},", serviceId,
                  registration.toString(), e);
    }
}

关键代码在namingService.registerInstance(serviceId, instance);,发现它最终调用com.alibaba.nacos.client.naming.NacosNamingService#registerInstance(java.lang.String, java.lang.String, com.alibaba.nacos.api.naming.pojo.Instance)方法

5.看com.alibaba.nacos.client.naming.NacosNamingService#registerInstance(java.lang.String, java.lang.String, com.alibaba.nacos.api.naming.pojo.Instance)方法。
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {

    if (instance.isEphemeral()) {
        BeatInfo beatInfo = new BeatInfo();
        beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
        beatInfo.setIp(instance.getIp());
        beatInfo.setPort(instance.getPort());
        beatInfo.setCluster(instance.getClusterName());
        beatInfo.setWeight(instance.getWeight());
        beatInfo.setMetadata(instance.getMetadata());
        beatInfo.setScheduled(false);
        long instanceInterval = instance.getInstanceHeartBeatInterval();
        beatInfo.setPeriod(instanceInterval == 0 ? DEFAULT_HEART_BEAT_INTERVAL : instanceInterval);

        beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);
    }

    serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
}

看前一部分的代码是如果该接待为一个临时节点,则组装心跳包,然后放在beatReactor里

后一部分的代码是调用com.alibaba.nacos.client.naming.net.NamingProxy#registerService注册服务。

6. 查看com.alibaba.nacos.client.naming.net.NamingProxy#registerService的代码
  public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
  
          NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}",
              namespaceId, serviceName, instance);
  
          final Map<String, String> params = new HashMap<String, String>(9);
          params.put(CommonParams.NAMESPACE_ID, namespaceId);
          params.put(CommonParams.SERVICE_NAME, serviceName);
          params.put(CommonParams.GROUP_NAME, groupName);
          params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
          params.put("ip", instance.getIp());
          params.put("port", String.valueOf(instance.getPort()));
          params.put("weight", String.valueOf(instance.getWeight()));
          params.put("enable", String.valueOf(instance.isEnabled()));
          params.put("healthy", String.valueOf(instance.isHealthy()));
          params.put("ephemeral", String.valueOf(instance.isEphemeral()));
          params.put("metadata", JSON.toJSONString(instance.getMetadata()));
  
          reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST);

      }

组装要注册的信息,然后调用com.alibaba.nacos.client.naming.net.NamingProxy#reqAPI(java.lang.String, java.util.Map<java.lang.String,java.lang.String>, java.lang.String)方法。查看该方法得知,此方法是调用一个Http请求,故此时是进行一个url为/nacos/v1/ns/instance的post请求。

我们下载版本为1.3.1的nacos源码可得知url为/nacos/v1/ns/instance的post请求干了什么事。

1.2 nacos server的服务注册请求

1. 查看com.alibaba.nacos.naming.controllers.InstanceController源代码。发现com.alibaba.nacos.naming.controllers.InstanceController#register处理post请求。
@CanDistro
@PostMapping
@Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE)
public String register(HttpServletRequest request) throws Exception {

    final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
    final String namespaceId = WebUtils
        .optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);

    final Instance instance = parseInstance(request);

    serviceManager.registerInstance(namespaceId, serviceName, instance);
    return "ok";
}

实际上是调用com.alibaba.nacos.naming.core.ServiceManager#registerInstance方法

2. 查看com.alibaba.nacos.naming.core.ServiceManager#registerInstance方法
 public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
        
     createEmptyService(namespaceId, serviceName, instance.isEphemeral());

     Service service = getService(namespaceId, serviceName);

     if (service == null) {
         throw new NacosException(NacosException.INVALID_PARAM,
                                  "service not found, namespace: " + namespaceId + ", service: " + serviceName);
     }

     addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
 }

从代码上看,第一步createEmptyService是创建了一个空服务。

createEmptyService实际上是调用了createServiceIfAbsent方法,看下createServiceIfAbsent方法

public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
            throws NacosException {
        Service service = getService(namespaceId, serviceName);
        if (service == null) {
            
            Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
            service = new Service();
            service.setName(serviceName);
            service.setNamespaceId(namespaceId);
            service.setGroupName(NamingUtils.getGroupName(serviceName));
            // now validate the service. if failed, exception will be thrown
            service.setLastModifiedMillis(System.currentTimeMillis());
            service.recalculateChecksum();
            if (cluster != null) {
                cluster.setService(service);
                service.getClusterMap().put(cluster.getName(), cluster);
            }
            service.validate();
            
            putServiceAndInit(service);
            if (!local) {
                addOrReplaceService(service);
            }
        }
    }

解析:

  • getService看看根据namespaceId和ServiceName得到看看是否有旧服务。
  • 如果没有就服务,组装服务信息,调用putServiceAndInit方法

putServiceAndInit方法解析

private void putServiceAndInit(Service service) throws NacosException {
        putService(service);
        service.init();
        consistencyService
                .listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
        consistencyService
                .listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
        Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJson());
    }

解析:

  • putService:

    public void putService(Service service) {
            if (!serviceMap.containsKey(service.getNamespaceId())) {
                synchronized (putServiceLock) {
                    if (!serviceMap.containsKey(service.getNamespaceId())) {
                        serviceMap.put(service.getNamespaceId(), new ConcurrentHashMap<>(16));
                    }
                }
            }
            serviceMap.get(service.getNamespaceId()).put(service.getName(), service);
        }
    

    以namespaceId为key,把service塞进以Map<String, Map<String, Service>> serviceMap里,这里的第一个key为nameSpaceId,第二个key为serviceName。

  • service.init();

     public void init() {
            HealthCheckReactor.scheduleCheck(clientBeatCheckTask);
            for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) {
                entry.getValue().setService(this);
                entry.getValue().init();
            }
        }
    
    • scheduleCheck

       public static void scheduleCheck(ClientBeatCheckTask task) {
           futureMap.putIfAbsent(task.taskKey(), GlobalExecutor.scheduleNamingHealth(task, 5000, 5000, TimeUnit.MILLISECONDS));
       }
      

    发起每隔5秒定时任务进行系统检查心跳检查

  • consistencyService.listen

    初始化数据一致性协议的监听器。

2、nacos服务发现

2.1 nacos客户端获取服务列表

1. 从feign和ribbon中获取根据服务名获取服务地址列表,最后是定位到com.alibaba.nacos.client.naming.NacosNamingService#selectInstances(java.lang.String, java.lang.String, java.util.List<java.lang.String>, boolean, boolean)方法
@Override
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);
}

从ribbon调用过来的时候,这里的subscribe是为true的,所以走hostReactor.getServiceInfo方法。

2. 我们看hostReactor.getServiceInfo方法的源码
public ServiceInfo getServiceInfo(final String serviceName, final String clusters) {

    NAMING_LOGGER.debug("failover-mode: " + failoverReactor.isFailoverSwitch());
    String key = ServiceInfo.getKey(serviceName, clusters);
    if (failoverReactor.isFailoverSwitch()) {
        return failoverReactor.getService(key);
    }
	//从内存中去取服务信息
    ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);
	//如果直接内存中取到为null
    if (null == serviceObj) {
        serviceObj = new ServiceInfo(serviceName, clusters);

        serviceInfoMap.put(serviceObj.getKey(), serviceObj);
		//更新之前放在updatingMap中
        updatingMap.put(serviceName, new Object());
        updateServiceNow(serviceName, clusters);
        //更新后移除
        updatingMap.remove(serviceName);
	
    } 
    //如果此服务正在更新中,则调用wait方法,进行阻塞
    else if (updatingMap.containsKey(serviceName)) {
        if (UPDATE_HOLD_INTERVAL > 0) {
            // hold a moment waiting for update finish
            synchronized (serviceObj) {
                try {
                    serviceObj.wait(UPDATE_HOLD_INTERVAL);
                } catch (InterruptedException e) {
                    NAMING_LOGGER.error("[getServiceInfo] serviceName:" + serviceName + ", clusters:" + clusters, e);
                }
            }
        }
    }
	//定时更新服务列表
    scheduleUpdateIfAbsent(serviceName, clusters);
    return serviceInfoMap.get(serviceObj.getKey());
}
  • 此方法中调用的updateServiceNow和scheduleUpdateIfAbsent是我们所关注的,查看源码

    updateServiceNow:

    public void updateServiceNow(String serviceName, String clusters) {
        ServiceInfo oldService = getServiceInfo0(serviceName, clusters);
        try {
    //得到之前组装的ServiceInfo,调用serverProxy.queryList
            String result = serverProxy.queryList(serviceName, clusters, pushReceiver.getUDPPort(), false);
            if (StringUtils.isNotEmpty(result)) {
                //组装返回的结果为ServiceInfo,并更新旧的服务列表
                processServiceJSON(result);
            }
        } catch (Exception e) {
            NAMING_LOGGER.error("[NA] failed to update serviceName: " + serviceName, e);
        } finally {
            if (oldService != null) {
                synchronized (oldService) {
                    //通知服务已经更新,终止之前的wait方法
                    oldService.notifyAll();
                }
            }
        }
    }
    
    • 查看serverProxy.queryList的源码

      public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly)
          throws NacosException {
      	//组装nacos server向client推送的udp端口,当前的ip,和健康状态,然后调用rest请求
          final Map<String, String> params = new HashMap<String, String>(8);
          params.put(CommonParams.NAMESPACE_ID, namespaceId);
          params.put(CommonParams.SERVICE_NAME, serviceName);
          params.put("clusters", clusters);
          params.put("udpPort", String.valueOf(udpPort));
          params.put("clientIP", NetUtils.localIP());
          params.put("healthyOnly", String.valueOf(healthyOnly));
      
          return reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/list", params, HttpMethod.GET);
      }
      
  • scheduleUpdateIfAbsent

    public void scheduleUpdateIfAbsent(String serviceName, String clusters) {
        if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
            return;
        }
    	
        synchronized (futureMap) {
            if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
                return;
            }
    		//开启一个定时pull服务列表的任务,从addTask方法中得知延时1s后执行
            ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
            futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
        }
    }
    

    我们看看com.alibaba.nacos.client.naming.core.HostReactor.UpdateTask的源码

    public class UpdateTask implements Runnable {
        long lastRefTime = Long.MAX_VALUE;
        private String clusters;
        private String serviceName;
    
        public UpdateTask(String serviceName, String clusters) {
            this.serviceName = serviceName;
            this.clusters = clusters;
        }
    
        @Override
        public void run() {
            try {
               //获得服务信息
                ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
    			//如果服务信息仍然为空,则进行updateServiceNow操作,并在1s之后仍然调用。
                if (serviceObj == null) {
                    updateServiceNow(serviceName, clusters);
                    executor.schedule(this, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
                    return;
                }
                //如果服务的最后更新小于或者等于上一次更新时间,则再进行更新,即定时拉去
                if (serviceObj.getLastRefTime() <= lastRefTime) {
                    updateServiceNow(serviceName, clusters);
                    serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));
                } else {
                    //如果服务的最后更新时间大于上一次更新时间,说明通过push机制更新过,则无需再更新
                    // if serviceName already updated by push, we should not override it
                    // since the push data may be different from pull through force push
                    refreshOnly(serviceName, clusters);
                }
    			//根据服务信息的缓存时间来进行下一次的pull请求
                executor.schedule(this, serviceObj.getCacheMillis(), TimeUnit.MILLISECONDS);
    
                lastRefTime = serviceObj.getLastRefTime();
            } catch (Throwable e) {
                NAMING_LOGGER.warn("[NA] failed to update serviceName: " + serviceName, e);
            }
    
        }
    }
    

2.2 nacos服务端处理获取服务列表消息

1. 通过下载的源码找到接受此请求的方法为com.alibaba.nacos.naming.controllers.InstanceController#list
@GetMapping("/list")
@Secured(parser = NamingResourceParser.class, action = ActionTypes.READ)
public ObjectNode 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);
    String agent = WebUtils.getUserAgent(request);
    String clusters = WebUtils.optional(request, "clusters", StringUtils.EMPTY);
    String clientIP = WebUtils.optional(request, "clientIP", StringUtils.EMPTY);
    int udpPort = Integer.parseInt(WebUtils.optional(request, "udpPort", "0"));
    String env = WebUtils.optional(request, "env", StringUtils.EMPTY);
    boolean isCheck = Boolean.parseBoolean(WebUtils.optional(request, "isCheck", "false"));

    String app = WebUtils.optional(request, "app", StringUtils.EMPTY);

    String tenant = WebUtils.optional(request, "tid", StringUtils.EMPTY);

    boolean healthyOnly = Boolean.parseBoolean(WebUtils.optional(request, "healthyOnly", "false"));

    return doSrvIpxt(namespaceId, serviceName, agent, clusters, clientIP, udpPort, env, isCheck, app, tenant,
                     healthyOnly);
}

前面的都是组装数据,重点是doSrvIpxt方法

/**
     * Get service full information with instances.
     *
     * @param namespaceId namespace id
     * @param serviceName service name
     * @param agent       agent infor string
     * @param clusters    cluster names
     * @param clientIP    client ip
     * @param udpPort     push udp port
     * @param env         env
     * @param isCheck     is check request
     * @param app         app name
     * @param tid         tenant
     * @param healthyOnly whether only for healthy check
     * @return service full information with instances
     * @throws Exception any error during handle
     */
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();
    //从内存中获取服务
    Service service = serviceManager.getService(namespaceId, serviceName);
    if (service == null) {
        //如果找不到,则返回一个空list的host给过去
        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.replace("hosts", JacksonUtils.createEmptyArrayNode());
        return result;
    }
	//检查服务是否可用
    checkIfDisabled(service);
	//缓存时间,默认3s,如果使用udp push,则设置成10s
    long cacheMillis = switchDomain.getDefaultCacheMillis();

    // now try to enable the push
    try { 
        //如果udp端口号大于0且客户端支持udp push,则添加一个客户端到pushService中,如果服务发生变更,则通过udp通讯通知
        if (udpPort > 0 && pushService.canEnablePush(agent)) {
            
            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();
    }

    List<Instance> srvedIPs;

    srvedIPs = service.srvIPs(Arrays.asList(StringUtils.split(clusters, ",")));

    // filter ips using selector:
    if (service.getSelector() != null && StringUtils.isNotBlank(clientIP)) {
        srvedIPs = service.getSelector().select(clientIP, srvedIPs);
    }
	//如果该服务下的可用ip为空,则直接组织返回
    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("hosts", JacksonUtils.createEmptyArrayNode());
        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.put("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();
    }

    if (isCheck) {
        result.put("protectThreshold", service.getProtectThreshold());
        result.put("reachLocalSiteCallThreshold", false);

        return JacksonUtils.createEmptyJsonNode();
    }

    ArrayNode hosts = JacksonUtils.createEmptyArrayNode();
//组织需要返回的数据
    for (Map.Entry<Boolean, List<Instance>> entry : ipMap.entrySet()) {
        List<Instance> ips = entry.getValue();

        if (healthyOnly && !entry.getKey()) {
            continue;
        }

        for (Instance instance : ips) {

            // remove disabled instance:
            if (!instance.isEnabled()) {
                continue;
            }

            ObjectNode ipObj = JacksonUtils.createEmptyJsonNode();

            ipObj.put("ip", instance.getIp());
            ipObj.put("port", instance.getPort());
            // deprecated since nacos 1.0.0:
            ipObj.put("valid", entry.getKey());
            ipObj.put("healthy", entry.getKey());
            ipObj.put("marked", instance.isMarked());
            ipObj.put("instanceId", instance.getInstanceId());
            ipObj.put("metadata", JacksonUtils.transferToJsonNode(instance.getMetadata()));
            ipObj.put("enabled", instance.isEnabled());
            ipObj.put("weight", instance.getWeight());
            ipObj.put("clusterName", instance.getClusterName());
            if (clientInfo.type == ClientInfo.ClientType.JAVA
                && clientInfo.version.compareTo(VersionUtil.parseVersion("1.0.0")) >= 0) {
                ipObj.put("serviceName", instance.getServiceName());
            } else {
                ipObj.put("serviceName", NamingUtils.getServiceName(instance.getServiceName()));
            }

            ipObj.put("ephemeral", instance.isEphemeral());
            hosts.add(ipObj);

        }
    }

    result.replace("hosts", hosts);
    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.replace("metadata", JacksonUtils.transferToJsonNode(service.getMetadata()));
    return result;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值