1. 背景

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

2. 分析一下

2.1 问题分析过程

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

关键是从哪找呢?具体步骤:知道服务启动方式。如Nacos,就是通过properties,那就找哪有用到启动的属性文件

项目用SpringBoot集成,那核心类的加载就在Spring.factories中。(这个文件会被springSPI加载到)

找到关键类

很凑巧,我们在spring.factories中找到了名字很像启动注册类的类。如下图:Spring.factories在找类的时候不要怕错,大胆猜,只要验证了自己的想法即可,不对就在接着找。

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

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

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

public class NacosServiceRegistryAutoConfiguration {

// 注册类实现,验证我们的想法,需要用到NacosDiscoverProperties @Bean

public 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 NacosAutoServiceRegistration

extends AbstractAutoServiceRegistration {

private NacosRegistration registration;

// 构造参数,关键 public NacosAutoServiceRegistration(ServiceRegistry serviceRegistry,

AutoServiceRegistrationProperties autoServiceRegistrationProperties,

NacosRegistration registration) {

super(serviceRegistry, autoServiceRegistrationProperties);

this.registration = registration;

}

// 注册方法 @Override

protected 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

implements AutoServiceRegistration, ApplicationContextAware,

ApplicationListener {

}

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

@Override

@SuppressWarnings("deprecation")

public void onApplicationEvent(WebServerInitializedEvent event) {

// 调用了bind方法 bind(event);

}

@Deprecated

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());

// 调用了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 below if (!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()方法就好啦。

@Override

public 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/1132 rethrowRuntimeException(e);

}

}

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

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

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

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

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

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

4. 总结

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

本地服务注册不上nacos_Nacos如何实现服务自动注册相关推荐

  1. 亚马逊云科技云服务概览(上):基础服务

    当我们向别人解释AWS云平台所包含的那些服务的时候,许多人对AWS服务种类的丰富程度都表示惊讶.对于部分听说过AWS的人来说,他们知道AWS云平台的功能主要限于EC2(弹性计算云).S3(简单存储服务 ...

  2. 民科微服务照片怎么上传_微服务 (为微信公众号提供服务)

    微服务 面向中小企业的微服务产品提供自动应答菜单.微网站生成与管理.微信CRM系统服务.微信公众平台客服服务等综合性的运营管理标准化服务,是多功能的微信运营管理平台. 微信管家是将企业微信公众账号通过 ...

  3. 本地服务注册不上nacos_SpringCloud War 包部署导致服务未正常注册到 Nacos 问题

    最近把一个 SpringBoot 项目接入了微服务,使用 SpringBoot 2.1.9.RELASE 和 SpringCloud Greewich.SR3 .本地测试都正常,但是上线后,出现了一个 ...

  4. Winform中实现FTP客户端并定时扫描指定路径下文件上传到FTP服务端然后删除文件

    场景 Windows10上怎样开启FTP服务: Windows10上怎样开启FTP服务_BADAO_LIUMANG_QIZHI的博客-CSDN博客 上面在Windows上搭建FTP服务器之后,会接收客 ...

  5. 在windows上部署IIS web服务

    在windows上部署IIS web服务 在windows上部署IIS web服务安装IIS相关环境并利用IIS服务器发布靶站源代码(注意应用程序池使用.net 4.0并开启.NET服务) 1.1程序 ...

  6. 【Discuz】原系统进入论坛自动注册并进行登录

    本文主要内容 重新写discuz的注册接口 从原系统进入论坛自动注册并登录 咔咔之前没有使用过discuz,本文只是我自己的解决方案,要是有更好的实现方式可以一起交流交流 先看看系统本来的注册源码 点 ...

  7. android 清单文件注册,在AndroidManifest(清单文件)中注册activity(活动)及配置主活动、更改App图标、App名称、修改隐藏标题栏...

    打开app/src/main/AndroidManifest. package="com.example.administrator.myapplication" > and ...

  8. Eclipse自动注册Servlet:web.xml注册和@Servlet注解 实现注册

    在创建Javaweb项目中要会用到大量的Servlet类,若一一手动注册会很繁琐,此时我们就得想办法实现web.xml自动注册了. Servlet自动注册的两种方法: 1.web.xml自动注册 2. ...

  9. 本地服务注册不上nacos_服务注册与发现—Nacos

    Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. Nacos 帮助您更敏捷和容易地构建.交付和管理微 ...

最新文章

  1. NSURLConnection 实现webView显示HTTPS页面
  2. android 异步刷新 方法,android应用中实现异步更新UI的方法有哪些
  3. VTK:网格质量用法实战
  4. Vlan和vtp重要的配置命令
  5. 如何升级成鸿蒙,如何将自己的华为手机升级成鸿蒙系统
  6. 归档-软考网规-存储部分-san-nas-das
  7. linux搭建mysql主从模式_Linux下搭建MySQL的主从复制(一)
  8. 11月全球搜索引擎市场:百度份额突破30% 增势持续
  9. 动态规划——最大整除子集C++
  10. 魏兴华_ORACLE优化器革命漫谈
  11. 黑苹果OC的血泪史之硬盘(三星固态1T)篇
  12. UE4 蓝图实现AI随机移动
  13. Android阿里云推送
  14. 外汇买入价、外汇卖出价、现钞买入价有什么区别?
  15. 亚马逊常见的报错问题应该如何处理?
  16. JAVA毕设项目喜枫日料店自助点餐系统(java+VUE+Mybatis+Maven+Mysql)
  17. golang profiling
  18. cf网络不稳定或服务器异常,电脑玩穿越火线为什么提示网络环境异常 - 卡饭网...
  19. 若依框架搜索框使用注解写动态SQL
  20. 这场金融网络盛宴 华为又要秀出哪些前瞻性布局?

热门文章

  1. Sentaurus TCAD学习之SVISUAL
  2. 正交曲面系下梯度散度旋度公式速记
  3. 如何在三个月内成为一名全栈开发
  4. UE4 随笔 反射标记符记录 持续更新
  5. JAVA JDBC 增删改查简单例子
  6. vue中数据异步更新($nextTick)的问题
  7. 备份数据上传腾讯云COS
  8. 在VS2013中开发QT,提示include ui_XXX.h文件错误
  9. HM代码阅读1: 帧间预测函数Void TEncSearch::predInterSearch()
  10. 准确率(Accuracy)、精度(Precision)、召回率(Recall)和 mAP 的图解