1. 背景

接着上次的说,Nacos问题的分析。这次就来分享一下自己的分析方法。以及如何利用Spring事件完成服务注册。

2. 分析一下

2.1 问题分析过程

问题是这样的,我以为是Nacos服务注册不上吗? 那就肯定是注册有问题了, 那就去找是服务是如何注册的。

关键是从哪找呢?具体步骤:

  1. 知道服务启动方式。如Nacos,就是通过properties,那就找哪有用到启动的属性文件
  2. 项目用SpringBoot集成,那核心类的加载就在Spring.factories中。(这个文件会被springSPI加载到)
  3. 找到关键类

很凑巧,我们在spring.factories中找到了名字很像启动注册类的类。如下图:

在找类的时候不要怕错,大胆猜,只要验证了自己的想法即可,不对就在接着找。

com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration类我们找到了,接下来就是去看这个类中的代码去验证自己的想法了。

2.2 Nacos是如何利用Spring事件来实现服务注册的?

com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration代码如下:

public class NacosServiceRegistryAutoConfiguration {// 注册类实现,验证我们的想法,需要用到NacosDiscoverProperties@Beanpublic NacosServiceRegistry nacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {return new NacosServiceRegistry(nacosDiscoveryProperties);}// 构建注册事例,依然要用到NacosDiscoverProperties@Bean@ConditionalOnBean(AutoServiceRegistrationProperties.class)public NacosRegistration nacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties,ApplicationContext context) {return new NacosRegistration(nacosDiscoveryProperties, context);}// 服务自动注册,通过上面实例化的两个类@Bean@ConditionalOnBean(AutoServiceRegistrationProperties.class)public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry,AutoServiceRegistrationProperties autoServiceRegistrationProperties,NacosRegistration registration) {return new NacosAutoServiceRegistration(registry,autoServiceRegistrationProperties, registration);}
}

通过查看代码,发现和我们猜想没有出入,是通过NacosDiscoverProperties来进行初始化,和官方给的Demo也相似(只是没继承SpringBoot,名字不叫这个),前面两个类我们先不用关注(好奇的可以先点进去看看),我们直接进入第三个方法NacosAutoServiceRegistration中,通过名字我们也可以看出,这个是自动注册的,参数中包含了Registry和Registration。我们进入类中接着查看。

public class NacosAutoServiceRegistrationextends AbstractAutoServiceRegistration<Registration> {private NacosRegistration registration;// 构造参数,关键public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,AutoServiceRegistrationProperties autoServiceRegistrationProperties,NacosRegistration registration) {super(serviceRegistry, autoServiceRegistrationProperties);this.registration = registration;}// 注册方法@Overrideprotected void register() {if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {log.debug("Registration disabled.");return;}if (this.registration.getPort() < 0) {this.registration.setPort(getPort().get());}// 调用了父类的注册方法super.register();}
}

进入类中,我们发现了register()方法,更进一步验证我们想法,是通过这个类来进行服务注册,但是在register()方法中,调用了父类的register()方法, 这点就要引起我们的好奇,父类都没都啥东西,调用父类的方法有啥用呢? 这个时候就想到了肯定有构造参数,或者方法初始化父类的东西啦!

我们观察构造参数,发现把serviceRegistry传入到了父类构造参数中,我们直接查看父类代码。

// 类
public abstract class AbstractAutoServiceRegistration<R extends Registration>implements AutoServiceRegistration, ApplicationContextAware,ApplicationListener<WebServerInitializedEvent> {}

AbstractAutoServiceRegistration是继承了ApplicationListener<WebServerInitializedEvent>,看到这,不就是我们熟悉的领域了吗?继承了ApplicationListener那就不多BB,直接看onApplicationEvent()方法就好啦。(这个事件是WebServerInitializedEvent,这点还是要知道的哈)

 @Override@SuppressWarnings("deprecation")public void onApplicationEvent(WebServerInitializedEvent event) {// 调用了bind方法bind(event);}@Deprecatedpublic 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());// 调用了start()方法this.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 belowif (!this.running.get()) {// 时间注册之前事件this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));// 调用了注册方法register();// 服务注册事件this.context.publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration()));this.running.compareAndSet(false, true);}}

start()方法里面还发布了两个事件,可见Spring中,服务的注册前后都有一些监听器来处理服务信息。先跳过这些,我们直接关注我们的核心——注册,直接进入register()方法中。

 protected void register() {// this.serviceRegistry 是我们传递进来的,// getRegistration() 是在NacosAutoServiceRegistration中实现的this.serviceRegistry.register(getRegistration());}

到这我们基本知道是怎么回事了,this.serviceRegistry是传递进来的,那调用的register()方法则是Nacos自己实现的注册,getRegistration()NacosServiceRegistryAutoConfiguration中通过nacosDiscoveryProperties生成的。那我们就看一下register()方法就好啦。

 @Overridepublic void register(Registration registration) {if (StringUtils.isEmpty(registration.getServiceId())) {log.warn("No service to register for nacos client...");return;}String serviceId = registration.getServiceId();String group = nacosDiscoveryProperties.getGroup();// 通过registration构建Instance实例Instance instance = getNacosInstanceFromRegistration(registration);try {// 向服务端发送注册请求namingService.registerInstance(serviceId, group, instance);log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,instance.getIp(), instance.getPort());}catch (Exception e) {log.error("nacos registry, {} register failed...{},", serviceId,registration.toString(), e);// rethrow a RuntimeException if the registration is failed.// issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132rethrowRuntimeException(e);}}

到这我们就看懂了,也知道大概流程了。流程图如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9hA0nfuW-1600526815943)(/Users/lifacheng/Documents/wenzhang/java/spring/004_nacos使用分析/002.jpg)]

3. 吸星大法:吸收代码经验

Spring 在实现的时候,通过设计模式(装饰),实现流程,又把关键部分丢给开发自己实现,提高了拓展性,然后巧妙的结合了观察者模式(变种),在合适的时间注册服务,妙啊~~

Nacos在实现的时候,深知Spring各种属性,各种用法,一定是对Spring有个深入了解的人(或者正好看过? 这个解释有点牵强),结合AutoRegistry和事件(不知道,肯定不知道怎么调用的),妙啊~~

看到这实现的代码,简直舒服,妙啊~~

xua~~~~(), 爽啊 ~~

4. 总结

总的看下来,这个启动,只能有Web容器的时候才能注册, 我猜主要是和namingServer注册有关,所以也不能算是一个bug了。

Nacos如何实现服务自动注册相关推荐

  1. 本地服务注册不上nacos_Nacos如何实现服务自动注册

    1. 背景 接着上次的说,Nacos问题的分析.这次就来分享一下自己的分析方法.以及如何利用Spring事件完成服务注册. 2. 分析一下 2.1 问题分析过程 问题是这样的,我以为是Nacos服务注 ...

  2. 利用zookeeper实现分布式服务故障自动剔除/服务自动注册的思路

    目前常见的web常规的负载均衡大多数是通过nginx的upstream配置将流量转发到内部的服务机上,来分担流量过多的情况,但是这里往往出现的一个问题是,nginx上配置服务器的ip是固定的,如果某台 ...

  3. 基于Curator实现dubbo服务自动注册发现

    文章目录 概念 基于ServiceDiscovery实现服务自动注册和发现 Service:服务基本信息 InstanceDetails:封装实例用过来保存到zk中 ServiceProvider:服 ...

  4. 本地服务注册不上nacos_dubbo + nacos 版本升级后服务无法注册成功

    原来版本是 dubbo 2.6.5 + nacos 0.0.1 可以正常注册和消费 换成dubbo 2.7.1后 原来的包名不匹配的问题没有了 但是无法正常注册 只是替换了dubbo 及 nacos的 ...

  5. nacos学习总结二(注册中心)

    Nacos Discovery 可以帮助您将服务自动注册到 Nacos 服务端并且能够动态感知和刷新某个服务实例的服务列表. 除此之外,Nacos Discovery 也将服务实例自身的一些元数据信息 ...

  6. 三、Spring Cloud Alibaba—nacos部署和服务发现

    一.什么是Nacos 官方地址: https://nacos.io/zh-cn/docs/v2/what-is-nacos.html 概念: 服务(Service)是 Nacos 世界的一等公民.Na ...

  7. Nacos服务的注册,服务的调用,修改配置文件自动刷新和命名空间

    一.nacos配置中心的配置 使用nacos作为配置中心,不需要再到远端仓库拉取配置文件. 详细的nacos控制台配置参见官方链接 二.服务的注册 创建项目并引入依赖 <!--引入nacos c ...

  8. 微服务框架 Go-Micro 集成 Nacos 实战之服务注册与发现

    作者 | 张斌斌 导读:本文主要介绍如何使用 Golang 生态中的微服务框架 Go-Micro(v2) 集成 Nacos 进行服务注册与发现.(Go-Micro 目前已经是 v3 版本,但由于某些原 ...

  9. 微服务框架Go-Micro集成Nacos实战之服务注册与发现

    简介:本文主要介绍如何使用 Golang 生态中的微服务框架 Go-Micro(v2) 集成 Nacos 进行服务注册与发现.(Go-Micro 目前已经是 v3 版本,但由于某些原因项目已经更名为 ...

最新文章

  1. hdu-1166敌兵布阵
  2. 中国电子学会图形化四级编程题:解密
  3. torch.mean
  4. mysql同步 触发器_mysql 触发器(数据库的同步)
  5. 【大话数据结构算法】查找算法
  6. JS简单正则得到字符串中特定的值
  7. 双向链表的操作(创建,插入,删除)
  8. python中读写excel_python读写Excel
  9. (map)出现最多的数
  10. multiset实现ALV树
  11. Docker 容器使用教程
  12. CSS3魔法堂:说说Multi-column Layout
  13. 视频直播系统源码,简单的移动端轮播图
  14. Linux系统下VMware虚拟机安装Win7 ISO操作系统
  15. 全球服务器系统排行,服务器操作系统排行榜
  16. 合天网安就业班_【合天网安实验室】SQL注入入门一
  17. 微信支付接口操作说明
  18. 更换kindle书籍的字体
  19. 【笔记-node】《imooc-nodejs入门到企业web开发中的应用》
  20. Intellij IDEA的永久破解网站

热门文章

  1. 签名JKS文件格式转换为KEYSTORE文件格式
  2. 长沙Uber优步司机奖励政策(3月28日)
  3. JRE的安装及环境变量配置
  4. 关于HCIE专栏资料
  5. 08从零开始学Java之记事本怎么编写Java代码?
  6. 火影忍者 22/8/16 项目流程
  7. Ubuntu 21.10 ALC294 声卡无声音、音量只能最大或静音问题的解决办法
  8. PHP版Sorry 真香GIF在线生成--添加GIF模板
  9. 基于Yolov5的交通标志检测识别设计
  10. PHP常用正则表达式