Spring启动的过程中nacos是如何发现注册服务的:
首先了解一下spring-cloud-commons包中的serviceRegistry接口,这是common包里通用抽象出来的服务注册接口(这里我理解就是spring暴露出来的接口有点像BeanFactory用于第三方集成使用,来管理第三方的Bean。这里是注册第三方的服务)
接口中操作的方法我们可以看到都操作的是Registration,所以nacos注册的时候:
第一:必然要实现这个接口,并且实现register()方法
第二:要实现这个方法,就需要一个Registration的子类
所以我们找到了如下的关系图
重点就在NacosServiceRegistry和NacosRegistration这两个类上
NacosRegistration这个类主要是准备服务实例的一些属性,我们的重点在于查看服务是如何被发现和注册的,
使用idea功能的find Usages找到register()方法被调用的地方:
是在抽象类 AbstractAutoServiceRegistration中调用,而它的子类NacosAutoServiceRegistration重写了这个方法。
所以到目前为止调用链是这样的:
NacosAutoServiceRegistration register()-->AbstractAutoServiceRegistration register()-->NacosServiceRegistry register()-->NamingService registerInstance()
AbstractAutoServiceRegistration类实现了ApplicationListener接口,这是一个时间监听,监听的是WebServerInitializedEvent事件,对spring的这个机制比较了解的话其实我们可以直接看类中重写的onApplicationEvent方法,就可以跟踪下来调用过程:
以上说的监听的事件执行onApplicationEvent方法的前提是,必须有applicationcontext.publishEvent(Event)
现在我们就去寻找publishEvent(WebServerInitializedEvent)在哪里调用的
跟踪过spring的启动过程都知道refresh方法,这是spring初始化的核心方法,想要了解refresh中都做了哪些事可以查查相关博客,有很多。
我们在这里只关注this.finishRefresh()这个方法
此时我们的方法是在AbstractApplicationContext类中,这是个抽象类有诸子类分别代表类型不同的容器,我们常用的就是ServletWebServerApplicationContext、ReactiveWebServerApplicationContext、XmlServletWebServerApplicationContext
我理解的关于AbstractApplicationContext这些子类,都有自己不同的启动方式(这里表述的不太清楚,待研究后补充完成)。
大家注意一下webServer的值,所以finishRefresh方法走的是ServletWebServerApplicationContext的重写,至此 我们就找到了publishEvent事件
NamingService registerInstance()方法概览:
心跳:通过ScheduledExecutorService定时任务不停的通过http发送心跳信息BeatInfo
注册:调用Nacos的api: /nacos/v1/ns/instance进行服务的注册,POST请求