Nacos 服务注册

  • nacos-spring-boot-project 中有关服务注册的几个项目
    • nacos-discovery-spring-boot-actuator nacos-discovery-spring-boot-autoconfigure nacos-discovery-spring-boot-starter
  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. com.alibaba.boot.nacos.discovery.autoconfigure.NacosDiscoveryAutoConfiguration

找到类 NacosDiscoveryAutoConfiguration

  1. @ConditionalOnProperty(name = NacosDiscoveryConstants.ENABLED, matchIfMissing = true)
  2. @ConditionalOnMissingBean(name = DISCOVERY_GLOBAL_NACOS_PROPERTIES_BEAN_NAME)
  3. @EnableNacosDiscovery
  4. @EnableConfigurationProperties(value = NacosDiscoveryProperties.class)
  5. @ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder")
  6. public class NacosDiscoveryAutoConfiguration {
  7. @Bean
  8. public NacosDiscoveryAutoRegister discoveryAutoRegister() {
  9. return new NacosDiscoveryAutoRegister();
  10. }
  11. }
  • 注解:EnableNacosDiscovery
  1. @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(NacosDiscoveryBeanDefinitionRegistrar.class)
  5. public @interface EnableNacosDiscovery {}
  • import 类 :NacosDiscoveryBeanDefinitionRegistrar
  1. public class NacosDiscoveryBeanDefinitionRegistrar
  2. implements ImportBeanDefinitionRegistrar, EnvironmentAware {
  3. private Environment environment;
  4. @Override
  5. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
  6. BeanDefinitionRegistry registry) {
  7. AnnotationAttributes attributes = AnnotationAttributes
  8. .fromMap(importingClassMetadata
  9. .getAnnotationAttributes(EnableNacosDiscovery.class.getName()));
  10. // Register Global Nacos Properties Bean
  11. registerGlobalNacosProperties(attributes, registry, environment,
  12. DISCOVERY_GLOBAL_NACOS_PROPERTIES_BEAN_NAME);
  13. registerGlobalNacosProperties(attributes, registry, environment,
  14. MAINTAIN_GLOBAL_NACOS_PROPERTIES_BEAN_NAME);
  15. // Register Nacos Common Beans
  16. registerNacosCommonBeans(registry);
  17. // Register Nacos Discovery Beans
  18. registerNacosDiscoveryBeans(registry);
  19. }
  20. @Override
  21. public void setEnvironment(Environment environment) {
  22. this.environment = environment;
  23. }
  24. }
  • 两个流程

    1. 将注解EnableNacosDiscovery的属性读取,放入到 nacos 的全局属性配置中

    2. bean 注入

nacos 全局配置属性

  • com.alibaba.nacos.spring.context.annotation.discovery.NacosDiscoveryBeanDefinitionRegistrar#registerBeanDefinitions
    • com.alibaba.nacos.spring.util.NacosBeanUtils#registerGlobalNacosProperties(org.springframework.core.annotation.AnnotationAttributes, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.core.env.PropertyResolver, java.lang.String)
  1. public static void registerGlobalNacosProperties(AnnotationAttributes attributes,
  2. BeanDefinitionRegistry registry, PropertyResolver propertyResolver,
  3. String beanName) {
  4. if (attributes == null) {
  5. return; // Compatible with null
  6. }
  7. AnnotationAttributes globalPropertiesAttributes = attributes
  8. .getAnnotation("globalProperties");
  9. registerGlobalNacosProperties((Map<?, ?>) globalPropertiesAttributes, registry,
  10. propertyResolver, beanName);
  11. }
  • 贴出注解上的信息
  1. NacosProperties globalProperties() default @NacosProperties(username = USERNAME_PLACEHOLDER, password = PASSWORD_PLACEHOLDER, endpoint = ENDPOINT_PLACEHOLDER, namespace = NAMESPACE_PLACEHOLDER, accessKey = ACCESS_KEY_PLACEHOLDER, secretKey = SECRET_KEY_PLACEHOLDER, serverAddr = SERVER_ADDR_PLACEHOLDER, contextPath = CONTEXT_PATH_PLACEHOLDER, clusterName = CLUSTER_NAME_PLACEHOLDER, encode = ENCODE_PLACEHOLDER);
  • 通过下面这段代码会将注解信息获取到对象AnnotationAttributes globalPropertiesAttributes

    1. AnnotationAttributes globalPropertiesAttributes = attributes
    2. .getAnnotation("globalProperties");
  • 下一段代码是将属性换算出来

    ```java registerGlobalNacosProperties((Map<?, ?>) globalPropertiesAttributes, registry,

    1. propertyResolver, beanName)
  1. public static void registerGlobalNacosProperties(Map<?, ?> globalPropertiesAttributes,
  2. BeanDefinitionRegistry registry, PropertyResolver propertyResolver,
  3. String beanName) {
  4. // 占位符解析成具体的配置信息
  5. Properties globalProperties = resolveProperties(globalPropertiesAttributes,
  6. propertyResolver);
  7. // 单例注册
  8. registerSingleton(registry, beanName, globalProperties);
  9. }
  1. ![image-20200821111938485](/uploads/projects/SpringBoot-source/images/nacos/image-20200821111938485.png)
  2. ## registerNacosCommonBeans

public static void registerNacosCommonBeans(BeanDefinitionRegistry registry) { // Register NacosApplicationContextHolder Bean registerNacosApplicationContextHolder(registry); // Register AnnotationNacosInjectedBeanPostProcessor Bean registerAnnotationNacosInjectedBeanPostProcessor(registry); }

  1. - 主要方法: registerInfrastructureBean
  2. 1. 定义出 bean
  3. 2. 设置构造参数
  4. 3. 注册对象
  5. ```java
  6. public static void registerInfrastructureBean(BeanDefinitionRegistry registry,
  7. String beanName, Class<?> beanClass, Object... constructorArgs) {
  8. // Build a BeanDefinition for NacosServiceFactory class
  9. // 定义出 bean 根据类型
  10. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
  11. .rootBeanDefinition(beanClass);
  12. for (Object constructorArg : constructorArgs) {
  13. beanDefinitionBuilder.addConstructorArgValue(constructorArg);
  14. }
  15. // ROLE_INFRASTRUCTURE
  16. beanDefinitionBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  17. // Register
  18. registry.registerBeanDefinition(beanName,
  19. beanDefinitionBuilder.getBeanDefinition());
  20. }

@EnableConfigurationProperties(value = NacosDiscoveryProperties.class)

属性读取,从 application 配置文件中读取数据转换成 java 对象。

image-20200821132413628

NacosDiscoveryAutoRegister

  1. public class NacosDiscoveryAutoRegister
  2. implements ApplicationListener<WebServerInitializedEvent> {}
  • 处理一个WebServerInitializedEvent 事件的方法

  • 重写方法如下,主要工作内容

    1. 把服务发现配置读取出来
    2. 设置一些数据值
    3. 调用服务注册接口
  1. @Override
  2. public void onApplicationEvent(WebServerInitializedEvent event) {
  3. if (!discoveryProperties.isAutoRegister()) {
  4. return;
  5. }
  6. Register register = discoveryProperties.getRegister();
  7. if (StringUtils.isEmpty(register.getIp())) {
  8. register.setIp(NetUtils.localIP());
  9. }
  10. if (register.getPort() == 0) {
  11. register.setPort(event.getWebServer().getPort());
  12. }
  13. register.getMetadata().put("preserved.register.source", "SPRING_BOOT");
  14. register.setInstanceId("");
  15. String serviceName = register.getServiceName();
  16. if (StringUtils.isEmpty(serviceName)){
  17. if (StringUtils.isEmpty(applicationName)){
  18. throw new AutoRegisterException("serviceName notNull");
  19. }
  20. serviceName = applicationName;
  21. }
  22. try {
  23. namingService.registerInstance(serviceName, register.getGroupName(),
  24. register);
  25. logger.info("Finished auto register service : {}, ip : {}, port : {}",
  26. serviceName, register.getIp(), register.getPort());
  27. } catch (NacosException e) {
  28. throw new AutoRegisterException(e);
  29. }
  30. }
  • 注册的参数

    image-20200821133350982

服务注册

image-20200821133445090

  • 注册一个实例
    1. 将 instance 对象转换成 BeatInfo 对象
    2. 注册实例
  1. @Override
  2. public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
  3. if (instance.isEphemeral()) {
  4. // 实例信息转换
  5. BeatInfo beatInfo = new BeatInfo();
  6. beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
  7. beatInfo.setIp(instance.getIp());
  8. beatInfo.setPort(instance.getPort());
  9. beatInfo.setCluster(instance.getClusterName());
  10. beatInfo.setWeight(instance.getWeight());
  11. beatInfo.setMetadata(instance.getMetadata());
  12. beatInfo.setScheduled(false);
  13. beatInfo.setPeriod(instance.getInstanceHeartBeatInterval());
  14. // 插入这条实例的信息
  15. beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName),
  16. beatInfo);
  17. }
  18. serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);
  19. }
  • addBeatInfo
    • 创建了一个定时任务 BeatTask
  1. public void addBeatInfo(String serviceName, BeatInfo beatInfo) {
  2. NAMING_LOGGER.info("[BEAT] adding beat: {} to beat map.", beatInfo);
  3. String key = buildKey(serviceName, beatInfo.getIp(), beatInfo.getPort());
  4. BeatInfo existBeat = null;
  5. //fix #1733
  6. if ((existBeat = dom2Beat.remove(key)) != null) {
  7. existBeat.setStopped(true);
  8. }
  9. dom2Beat.put(key, beatInfo);
  10. executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
  11. MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
  12. }

BeatTask

  1. class BeatTask implements Runnable {
  2. BeatInfo beatInfo;
  3. public BeatTask(BeatInfo beatInfo) {
  4. this.beatInfo = beatInfo;
  5. }
  6. @Override
  7. public void run() {
  8. if (beatInfo.isStopped()) {
  9. return;
  10. }
  11. long nextTime = beatInfo.getPeriod();
  12. try {
  13. // 与nacos进行一次rest请求交互
  14. JSONObject result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);
  15. long interval = result.get(CLIENT_BEAT_INTERVAL_FIELD).asLong();
  16. boolean lightBeatEnabled = false;
  17. if (result.has(CommonParams.LIGHT_BEAT_ENABLED)) {
  18. lightBeatEnabled = result.get(CommonParams.LIGHT_BEAT_ENABLED).asBoolean();
  19. }
  20. BeatReactor.this.lightBeatEnabled = lightBeatEnabled;
  21. if (interval > 0) {
  22. nextTime = interval;
  23. }
  24. int code = NamingResponseCode.OK;
  25. if (result.has(CommonParams.CODE)) {
  26. code = result.get(CommonParams.CODE).asInt();
  27. }
  28. // 如果nacos找不到当前实例,
  29. if (code == NamingResponseCode.RESOURCE_NOT_FOUND) {
  30. Instance instance = new Instance();
  31. instance.setPort(beatInfo.getPort());
  32. instance.setIp(beatInfo.getIp());
  33. instance.setWeight(beatInfo.getWeight());
  34. instance.setMetadata(beatInfo.getMetadata());
  35. instance.setClusterName(beatInfo.getCluster());
  36. instance.setServiceName(beatInfo.getServiceName());
  37. instance.setInstanceId(instance.getInstanceId());
  38. instance.setEphemeral(true);
  39. try {
  40. // 执行注册服务
  41. serverProxy.registerService(beatInfo.getServiceName(),
  42. NamingUtils.getGroupName(beatInfo.getServiceName()), instance);
  43. } catch (Exception ignore) {
  44. }
  45. }
  46. } catch (NacosException ne) {
  47. NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, code: {}, msg: {}",
  48. JSON.toJSONString(beatInfo), ne.getErrCode(), ne.getErrMsg());
  49. } catch (Exception unknownEx) {
  50. NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, unknown exception msg: {}",
  51. JacksonUtils.toJson(beatInfo), unknownEx.getMessage(), unknownEx);
  52. } finally {
  53. executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS);
  54. }
  55. }
  56. }
  • 定时任务说明

    1. 和 nacos 进行一次交互,根据交互结果的 code 判断,如果不在 nacos 会执行注册.
  • 发送请求的方法

    1. public String reqAPI(String api, Map<String, String> params, String body, List<String> servers, String method) throws NacosException {
    2. params.put(CommonParams.NAMESPACE_ID, getNamespaceId());
    3. if (CollectionUtils.isEmpty(servers) && StringUtils.isEmpty(nacosDomain)) {
    4. throw new NacosException(NacosException.INVALID_PARAM, "no server available");
    5. }
    6. NacosException exception = new NacosException();
    7. if (serverListManager.isDomain()) {
    8. String nacosDomain = serverListManager.getNacosDomain();
    9. for (int i = 0; i < maxRetry; i++) {
    10. try {
    11. return callServer(api, params, body, nacosDomain, method);
    12. } catch (NacosException e) {
    13. exception = e;
    14. if (NAMING_LOGGER.isDebugEnabled()) {
    15. NAMING_LOGGER.debug("request {} failed.", nacosDomain, e);
    16. }
    17. }
    18. }
    19. } else {
    20. Random random = new Random(System.currentTimeMillis());
    21. int index = random.nextInt(servers.size());
    22. for (int i = 0; i < servers.size(); i++) {
    23. String server = servers.get(index);
    24. try {
    25. return callServer(api, params, body, server, method);
    26. } catch (NacosException e) {
    27. exception = e;
    28. if (NAMING_LOGGER.isDebugEnabled()) {
    29. NAMING_LOGGER.debug("request {} failed.", server, e);
    30. }
    31. }
    32. index = (index + 1) % servers.size();
    33. }
    34. }
    35. NAMING_LOGGER.error("request: {} failed, servers: {}, code: {}, msg: {}", api, servers, exception.getErrCode(),
    36. exception.getErrMsg());
    37. throw new NacosException(exception.getErrCode(),
    38. "failed to req API:" + api + " after all servers(" + servers + ") tried: " + exception.getMessage());

学习点

  • 这里采用随机值作为第一个 server 的获取,主要目的是为了将请求随机分配给不同的 nacos 服务

    如果直接使用 for 循环的索引那第一台 nacos 服务会收到所有的请求,直到这台服务坏了才会请求第二台

    1. Random random = new Random(System.currentTimeMillis());
    2. int index = random.nextInt(servers.size());
    3. for (int i = 0; i < servers.size(); i++) {
    4. // 获取nacos所在的ip+port地址
    5. String server = servers.get(index);
    6. try {
    7. // 进行请求
    8. return callServer(api, params, body, server, method);
    9. } catch (NacosException e) {
    10. exception = e;
    11. if (NAMING_LOGGER.isDebugEnabled()) {
    12. NAMING_LOGGER.debug("request {} failed.", server, e);
    13. }
    14. }
    15. index = (index + 1) % servers.size();
    16. }

    }

registerService

  • 注册方法就是请求一次接口,将数据发送给 nacos 就完成了
  1. public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
  2. NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}",
  3. namespaceId, serviceName, instance);
  4. String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
  5. if (instance.isEphemeral()) {
  6. BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
  7. beatReactor.addBeatInfo(groupedServiceName, beatInfo);
  8. }
  9. final Map<String, String> params = new HashMap<String, String>(32);
  10. params.put(CommonParams.NAMESPACE_ID, namespaceId);
  11. params.put(CommonParams.SERVICE_NAME, groupedServiceName);
  12. params.put(CommonParams.GROUP_NAME, groupName);
  13. params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
  14. params.put(IP_PARAM, instance.getIp());
  15. params.put(PORT_PARAM, String.valueOf(instance.getPort()));
  16. params.put(WEIGHT_PARAM, String.valueOf(instance.getWeight()));
  17. params.put(REGISTER_ENABLE_PARAM, String.valueOf(instance.isEnabled()));
  18. params.put(HEALTHY_PARAM, String.valueOf(instance.isHealthy()));
  19. params.put(EPHEMERAL_PARAM, String.valueOf(instance.isEphemeral()));
  20. params.put(META_PARAM, JacksonUtils.toJson(instance.getMetadata()));
  21. reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST);
  22. }
  • 服务注册的接口

    • /nacos/v1/ns/instance
    • /nacos/v1/ns/instance/beat
  • 接下来去寻找这两个接口的实现

    com.alibaba.nacos.naming.controllers.InstanceController

nacos 服务端

实例注册

  1. public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
  2. // 创建空服务
  3. createEmptyService(namespaceId, serviceName, instance.isEphemeral());
  4. Service service = getService(namespaceId, serviceName);
  5. if (service == null) {
  6. throw new NacosException(NacosException.INVALID_PARAM,
  7. "service not found, namespace: " + namespaceId + ", service: " + serviceName);
  8. }
  9. addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
  10. }
  • 创建空服务的流程

    • 获取服务对象

      nacos 的服务信息存储在

      com.alibaba.nacos.naming.core.ServiceManager#serviceMap

      1. private Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
  1. public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster) throws NacosException {
  2. // 获取服务信息
  3. Service service = getService(namespaceId, serviceName);
  4. if (service == null) {
  5. Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
  6. service = new Service();
  7. service.setName(serviceName);
  8. service.setNamespaceId(namespaceId);
  9. service.setGroupName(NamingUtils.getGroupName(serviceName));
  10. // now validate the service. if failed, exception will be thrown
  11. service.setLastModifiedMillis(System.currentTimeMillis());
  12. service.recalculateChecksum();
  13. if (cluster != null) {
  14. cluster.setService(service);
  15. service.getClusterMap().put(cluster.getName(), cluster);
  16. }
  17. service.validate();
  18. putServiceAndInit(service);
  19. if (!local) {
  20. addOrReplaceService(service);
  21. }
  22. }
  23. }
  • 在了解 map 结构后不难理解下面这个获取 Service 的方法了
  1. public Service getService(String namespaceId, String serviceName) {
  2. if (serviceMap.get(namespaceId) == null) {
  3. return null;
  4. }
  5. return chooseServiceMap(namespaceId).get(serviceName);
  6. }
  1. private void putServiceAndInit(Service service) throws NacosException {
  2. putService(service);
  3. service.init();
  4. consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
  5. consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
  6. Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
  7. }
  • 把服务加入 map 对象
  1. public void putService(Service service) {
  2. if (!serviceMap.containsKey(service.getNamespaceId())) {
  3. synchronized (putServiceLock) {
  4. if (!serviceMap.containsKey(service.getNamespaceId())) {
  5. serviceMap.put(service.getNamespaceId(), new ConcurrentHashMap<>(16));
  6. }
  7. }
  8. }
  9. serviceMap.get(service.getNamespaceId()).put(service.getName(), service);
  10. }
  • init 方法设置了一个数据验证的任务 , 并且在集群中设置 service 信息
  1. public void init() {
  2. HealthCheckReactor.scheduleCheck(clientBeatCheckTask);
  3. for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) {
  4. entry.getValue().setService(this);
  5. entry.getValue().init();
  6. }
  7. }
  • 再往后添加两个 key 的监听

  • addInstance 方法

  1. public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips) throws NacosException {
  2. String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
  3. Service service = getService(namespaceId, serviceName);
  4. synchronized (service) {
  5. List<Instance> instanceList = addIpAddresses(service, ephemeral, ips);
  6. Instances instances = new Instances();
  7. instances.setInstanceList(instanceList);
  8. consistencyService.put(key, instances);
  9. }
  10. }
  • 简单理解 consistencyService 结构信息
    • key: 定义的一个名字
    • value : 实例的列表

实例健康检查

  • 获取实例独享, 从 service 中根据集群名称获取实例列表 , 再根据 ip + 端口 返回实例对象
  1. Instance instance = serviceManager.getInstance(namespaceId, serviceName, clusterName, ip, port);
  1. public Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port) {
  2. Service service = getService(namespaceId, serviceName);
  3. if (service == null) {
  4. return null;
  5. }
  6. List<String> clusters = new ArrayList<>();
  7. clusters.add(cluster);
  8. List<Instance> ips = service.allIPs(clusters);
  9. if (ips == null || ips.isEmpty()) {
  10. return null;
  11. }
  12. for (Instance instance : ips) {
  13. if (instance.getIp().equals(ip) && instance.getPort() == port) {
  14. return instance;
  15. }
  16. }
  17. return null;
  18. }
  • 实例健康检查接口做的事件
    1. 获取实例
      1. 实例不存在注册实例
    2. 获取服务
      1. 服务不存在抛出异常
      2. 服务存在执行一个心跳方法
    3. 组装结果返回
  1. @CanDistro
  2. @PutMapping("/beat")
  3. @Secured(action = ActionTypes.WRITE)
  4. public ObjectNode beat(@RequestParam(defaultValue = Constants.DEFAULT_NAMESPACE_ID) String namespaceId,
  5. @RequestParam String serviceName,
  6. @RequestParam(defaultValue = StringUtils.EMPTY) String ip,
  7. @RequestParam(defaultValue = UtilsAndCommons.DEFAULT_CLUSTER_NAME) String clusterName,
  8. @RequestParam(defaultValue = "0") Integer port,
  9. @RequestParam(defaultValue = StringUtils.EMPTY) String beat)throws Exception {
  10. ObjectNode result = JacksonUtils.createEmptyJsonNode();
  11. result.put(SwitchEntry.CLIENT_BEAT_INTERVAL, switchDomain.getClientBeatInterval());
  12. RsInfo clientBeat = null;
  13. if (StringUtils.isNotBlank(beat)) {
  14. clientBeat = JacksonUtils.toObj(beat, RsInfo.class);
  15. }
  16. if (clientBeat != null) {
  17. if (StringUtils.isNotBlank(clientBeat.getCluster())) {
  18. clusterName = clientBeat.getCluster();
  19. } else {
  20. // fix #2533
  21. clientBeat.setCluster(clusterName);
  22. }
  23. ip = clientBeat.getIp();
  24. port = clientBeat.getPort();
  25. }
  26. NamingUtils.checkServiceNameFormat(serviceName);
  27. Loggers.SRV_LOG.debug("[CLIENT-BEAT] full arguments: beat: {}, serviceName: {}, namespaceId: {}", clientBeat,
  28. serviceName, namespaceId);
  29. BeatInfoInstanceBuilder builder = BeatInfoInstanceBuilder.newBuilder();
  30. int resultCode = instanceServiceV2
  31. .handleBeat(namespaceId, serviceName, ip, port, clusterName, clientBeat, builder);
  32. result.put(CommonParams.CODE, resultCode);
  33. result.put(SwitchEntry.CLIENT_BEAT_INTERVAL,
  34. instanceServiceV2.getHeartBeatInterval(namespaceId, serviceName, ip, port, clusterName));
  35. result.put(SwitchEntry.LIGHT_BEAT_ENABLED, switchDomain.isLightBeatEnabled());
  36. return result;
  37. }