当前位置:   article > 正文

nacos源码 服务自动注册流程(ServiceRegistry)_nacosautoserviceregistration

nacosautoserviceregistration

目录

Springcloud 服务注册接口 ServiceRegistry


一、NacosServiceRegistryAutoConfiguration

  1. @Configuration(proxyBeanMethods = false)
  2. @EnableConfigurationProperties
  3. @ConditionalOnNacosDiscoveryEnabled
  4. # 默认开启服务自动注册
  5. @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
  6. matchIfMissing = true)
  7. @AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
  8. AutoServiceRegistrationAutoConfiguration.class,
  9. NacosDiscoveryAutoConfiguration.class })
  10. public class NacosServiceRegistryAutoConfiguration {
  11. @Bean
  12. public NacosServiceRegistry nacosServiceRegistry(
  13. NacosDiscoveryProperties nacosDiscoveryProperties) {
  14. return new NacosServiceRegistry(nacosDiscoveryProperties);
  15. }
  16. @Bean
  17. @ConditionalOnBean(AutoServiceRegistrationProperties.class)
  18. public NacosRegistration nacosRegistration(
  19. ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers,
  20. NacosDiscoveryProperties nacosDiscoveryProperties,
  21. ApplicationContext context) {
  22. return new NacosRegistration(registrationCustomizers.getIfAvailable(),
  23. nacosDiscoveryProperties, context);
  24. }
  25. @Bean
  26. @ConditionalOnBean(AutoServiceRegistrationProperties.class)
  27. public NacosAutoServiceRegistration nacosAutoServiceRegistration(
  28. NacosServiceRegistry registry,
  29. AutoServiceRegistrationProperties autoServiceRegistrationProperties,
  30. NacosRegistration registration) {
  31. return new NacosAutoServiceRegistration(registry,
  32. autoServiceRegistrationProperties, registration);
  33. }
  34. }

配置类中设计到的几个bean:NacosServiceRegistry 、NacosRegistration 、NacosAutoServiceRegistration 、AutoServiceRegistrationConfiguration

NacosServiceRegistry : 实现服务的注册逻辑

NacosRegistration : 通过 NacosRegistrationCustomizer 实现类定制化服务

NacosAutoServiceRegistration : 服务启动后自动注册的入口

AutoServiceRegistrationConfiguration : 用于注册 AutoServiceRegistrationProperties``

二、注册流程

1、NacosAutoServiceRegistration

它实现了ApplicationListener,监听 WebServerInitializedEvent 事件,

在spring容器启动过程中,WebServerStartStopLifecycle 发布了 ServletWebServerInitializedEvent

  1. public void start() {
  2. this.webServer.start();
  3. this.running = true;
  4. this.applicationContext.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
  5. }

2、bind( )

  1. AbstractAutoServiceRegistration.java
  2. public void bind(WebServerInitializedEvent event) {
  3. ApplicationContext context = event.getApplicationContext();
  4. if (context instanceof ConfigurableWebServerApplicationContext) {
  5. if ("management".equals(((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {
  6. return;
  7. }
  8. }
  9. //端口绑定
  10. this.port.compareAndSet(0, event.getWebServer().getPort());
  11. this.start();
  12. }

3、start( )

  1. public void start() {
  2. if (!isEnabled()) {
  3. if (logger.isDebugEnabled()) {
  4. logger.debug("Discovery Lifecycle disabled. Not starting");
  5. }
  6. return;
  7. }
  8. // only initialize if nonSecurePort is greater than 0 and it isn't already running
  9. // because of containerPortInitializer below
  10. if (!this.running.get()) {
  11. //发布服务注册前的事件
  12. this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));
  13. //服务注册
  14. register();
  15. if (shouldRegisterManagement()) {
  16. registerManagement();
  17. }
  18. //发布服务注册事件
  19. this.context.publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration()));
  20. //运行状态设置为true
  21. this.running.compareAndSet(false, true);
  22. }
  23. }

4、register( )

  1. @Override
  2. protected void register() {
  3. //校验注册功能是否打开
  4. if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
  5. log.debug("Registration disabled.");
  6. return;
  7. }
  8. if (this.registration.getPort() < 0) {
  9. this.registration.setPort(getPort().get());
  10. }
  11. //注册
  12. super.register();
  13. }
  14. protected void register() {
  15. //调用 NacosServiceRegistry
  16. this.serviceRegistry.register(getRegistration());
  17. }

5、register( )

  1. NacosServiceRegistry.java
  2. public void register(Registration registration) {
  3. if (StringUtils.isEmpty(registration.getServiceId())) {
  4. log.warn("No service to register for nacos client...");
  5. return;
  6. }
  7. //获取 NamingService
  8. NamingService namingService = namingService();
  9. String serviceId = registration.getServiceId();
  10. String group = nacosDiscoveryProperties.getGroup();
  11. Instance instance = getNacosInstanceFromRegistration(registration);
  12. try {
  13. //注册
  14. namingService.registerInstance(serviceId, group, instance);
  15. log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
  16. instance.getIp(), instance.getPort());
  17. }
  18. catch (Exception e) {
  19. log.error("nacos registry, {} register failed...{},", serviceId,
  20. registration.toString(), e);
  21. // rethrow a RuntimeException if the registration is failed.
  22. // issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132
  23. rethrowRuntimeException(e);
  24. }
  25. }

6、registerInstance( )

  1. @Override
  2. public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
  3. NamingUtils.checkInstanceIsLegal(instance);
  4. String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
  5. if (instance.isEphemeral()) {
  6. //构造心跳信息
  7. BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
  8. //开启心跳检测
  9. beatReactor.addBeatInfo(groupedServiceName, beatInfo);
  10. }
  11. //服务注册
  12. serverProxy.registerService(groupedServiceName, groupName, instance);
  13. }

7、addBeatInfo( )

  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. //创建心跳检测任务 BeatTask,线程池执行该任务
  11. executorService.schedule(new BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
  12. MetricsMonitor.getDom2BeatSizeMonitor().set(dom2Beat.size());
  13. }

8、registerService( )

调用nacos服务端注册服务

  1. public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
  2. NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName,
  3. instance);
  4. //构造请求参数
  5. final Map<String, String> params = new HashMap<String, String>(16);
  6. params.put(CommonParams.NAMESPACE_ID, namespaceId);
  7. params.put(CommonParams.SERVICE_NAME, serviceName);
  8. params.put(CommonParams.GROUP_NAME, groupName);
  9. params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
  10. params.put("ip", instance.getIp());
  11. params.put("port", String.valueOf(instance.getPort()));
  12. params.put("weight", String.valueOf(instance.getWeight()));
  13. params.put("enable", String.valueOf(instance.isEnabled()));
  14. params.put("healthy", String.valueOf(instance.isHealthy()));
  15. params.put("ephemeral", String.valueOf(instance.isEphemeral()));
  16. params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
  17. //通过 NamingProxy调用nacos api进行服务注册
  18. reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
  19. }

9、BeatTask
定时任务向nacos服务端发送心跳消息

  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 api心跳接口
  14. JsonNode result = serverProxy.sendBeat(beatInfo, BeatReactor.this.lightBeatEnabled);
  15. long interval = result.get("clientBeatInterval").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. //校验返回状态码
  25. int code = NamingResponseCode.OK;
  26. if (result.has(CommonParams.CODE)) {
  27. code = result.get(CommonParams.CODE).asInt();
  28. }
  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 ex) {
  47. NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: {}, code: {}, msg: {}",
  48. JacksonUtils.toJson(beatInfo), ex.getErrCode(), ex.getErrMsg());
  49. }
  50. //延时调度 BeatTask
  51. executorService.schedule(new BeatTask(beatInfo), nextTime, TimeUnit.MILLISECONDS);
  52. }
  53. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/315431
推荐阅读
相关标签
  

闽ICP备14008679号