一、配置中心源码解析
1.首先找到nacos读取配置的入口
1)找到nacos-config包下的spring.factories中的NacosConfigBootstrapConfiguration
2)NacosConfigBootstrapConfiguration会做两件事情,加载完成两个bean,一个是NacosConfigManager,另外一个是NacosPropertySourceLocator
先看NacosConfigManager是如何完成实例化操作的
然后再看createConfigService方法,该方法主要是为了创建ConfigService实例,创建的方式是通过反射来实现,对应的属性填充是由nacosConfigProperties来完成。
1>反射创建实例
2>nacosConfigProperties的assembleConfigServiceProperties方法来完成实例属性的填充
再看NacosPropertySourceLocator是如何实例化
该bean的实例化,是将上面生成好的nacosConfigManager以及nacosConfigProperites填充到当前类中
然后NacosPropertySourceLocator是继承了PropertySourceLocator类,重写了locate方法,此方法是由bootstrap上下文的SpringApplication.prepareContext方法中的applyInitializers里的PropertySourceBootstrapConfiguration.initialize调用
这个类是在SpringBoot启动的时候会去执行。找到SpringBoot启动的run方法,其中NacosPropertySourceLocator就是在prepareContext中开始执行。
然后找到prepareContext方法中的applyInitializers方法
找到PropertySourceBootstrapConfiguration类对应的initalize方法
initalize方法中遍历所有的PropertySourceLocator,然后再调用locateCollection,然后再调用PropertySourceLocator的子类NacosPropertySourceLocator的locate方法
然后再找到locate方法中的loadApplicationConfiguration方法,此方法就是开始准备要配置文件中的数据了。
然后找到loadNacosDataIfPresent方法,其中loadNacosPropertySource方法是最重要的一个方法,此方法中包含了获取配置的流程。
再找到NacosPropertySourceBuilder中的build方法
上图中真正加载配置数据的方法是loadNacosData方法
其中通过我们之前实例化好的ConfigService类,调用其getConfig方法获取配置数据
首先是通过dataId和group 来获取nacos本地配置
如果nacos的本地配置为空,则需要向服务端发送请求,获取服务配置。nacos 1.x 版本是通过http请求,在nacos 2.x 已经改为gRpc方式。
通过ClientWorker类的getServiceConfig来向服务端发送请求获取配置信息,其中ClientWorker在实例化的过程中也处理了一部分逻辑,这个后续来解释。
真正发送请求的是下图的代码
如果请求成功,则保存一份到本地,再返回。
二、服务的注册与发现
nacos实现动态发现和注册的原理,nacos 1.x之间的数据同步靠http协议同步,2.x版本后改成distro协议来同步数据。
注册与发现是通过订阅机制来实现的。客户端通过订阅注册中心,注册中心则会返回当前注册在注册中心的所有的实例,返回的数据就包含了其他客户端的ip和端口,则可以通过ip和端口对其他客户端服务进行访问和调用。
服务端的源码入口
找到nacos-discovery 的文件spring.factories,然后找到NacosServiceRegistryAutoConfiguration,nacos服务注册自动配置类。
这个类中,主要注册NacosAutoServiceRegistration类的bean实例
点击该类的构造方法,其实例化通过其父类AbstractAutoServiceRegistration的构造方法实现
其父类实现了ApplicationListener接口,这个接口可以监听容器中发布WebServerInitializedEvent事件,这个事件会在应用上下文刷新后和WebServer已经准备好之后被发布,然后触发onApplicationEvent,执行bind()方法。
然后再看start方法,方法中重点的方法是register()方法
其中register方法是调用了ServiceRegistry的子类NacosServiceRegistry的register方法
然后再看namingService的registerInstance方法
clientProxy是代理接口,通过其子类NamingGrpcClientProxy调用registerService方法来实现服务的注册逻辑
注册服务的逻辑中包含如下几个步骤:
1.redoService是去添加redo日志,实际上通过registeredInstances 的map结构来存储redo日志
2.doRegisterService是真正发起注册的逻辑,其中requestToServer 方法就是发送gRpc协议请求,去完成注册,然后instanceRegistered方法主要是标记当前服务已经完成注册逻辑。
requestToServer方法
实例注册成功后,会把redo日志中实例标记成注册成功