概述
从引入的 Nacos Discovery 的 starter 中找 spring.factories
文件,咱们能看到下图,既然是了解服务注册的,按照 Spring Boot 的习俗,咱们应该重点关注红框中的内容 NacosServiceRegistryAutoConfiguration
。
入口
从上面咱们知道了入口是 NacosServiceRegistryAutoConfiguration
,点进去看下:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
NacosDiscoveryAutoConfiguration.class })
public class NacosServiceRegistryAutoConfiguration {
@Bean
public NacosServiceRegistry nacosServiceRegistry(
NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(nacosServiceManager, nacosDiscoveryProperties);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosRegistration nacosRegistration(
ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers,
NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
return new NacosRegistration(registrationCustomizers.getIfAvailable(),
nacosDiscoveryProperties, context);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
}
@ConditionalOnXxxYyy
注解是一些条件注解,这里不再赘述,@AutoConfigureAfter
代表加载了制定的类之后再加载当前类。
NacosAutoServiceRegistration
public class NacosAutoServiceRegistration
extends AbstractAutoServiceRegistration<Registration> {
private static final Logger log = LoggerFactory
.getLogger(NacosAutoServiceRegistration.class);
private NacosRegistration registration;
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
// 省略部分代码
}
先看下类图,我们会发现通过继承实现了 ApplicationListener
接口的抽象类 AbstractAutoServiceRegistration
获得了以下能力:
public void onApplicationEvent(WebServerInitializedEvent event) {
bind(event);
}
AbstractAutoServiceRegistration
注册
AbstractAutoServiceRegistration#bind(WebServerInitializedEvent 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();
}
AbstractAutoServiceRegistration#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();
if (shouldRegisterManagement()) {
registerManagement();
}
// 发布注册事件
this.context.publishEvent(
new InstanceRegisteredEvent<>(this, getConfiguration()));
this.running.compareAndSet(false, true);
}
}
其中 register()
和 registerManagement()
都会调用到 ServiceRegistry#register(R registration)
NacosServiceRegistry
NacosServiceRegistry 是 ServiceRegistry 的一个实现。
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
return;
}
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
// 获取实例
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) {
if (nacosDiscoveryProperties.isFailFast()) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
rethrowRuntimeException(e);
}
else {
log.warn("Failfast is false. {} register failed...{},", serviceId,
registration.toString(), e);
}
}
}
NacosNamingService
public class NacosNamingService implements NamingService {
// 省略代码
private NamingClientProxy clientProxy;
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
NamingUtils.checkInstanceIsLegal(instance);
clientProxy.registerService(serviceName, groupName, instance);
}
看到最终是通过 clientProxy.registerService(serviceName, groupName, instance);
完成了实例的注册。
注销
回到 AbstractAutoServiceRegistration
类中,我们看到了被 @PreDestroy
标注的方法,含义是在应用程序关闭时执行被 @PreDestroy
标注的方法:
@PreDestroy
public void destroy() {
stop();
}
AbstractAutoServiceRegistration#stop()
public void stop() {
if (this.getRunning().compareAndSet(true, false) && isEnabled()) {
deregister();
if (shouldRegisterManagement()) {
deregisterManagement();
}
this.serviceRegistry.close();
}
}
其中 deregister()
以及 deregisterManagement()
都会执行 serviceRegistry.deregister(registration)
,进行服务的注销。
NacosServiceRegistry#deregister(Registration registration)
上文说到的 serviceRegistry 在 Nacos 中的实现是 NacosServiceRegistry,看下具体的方法:
@Override
public void deregister(Registration registration) {
log.info("De-registering from Nacos Server now...");
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No dom to de-register for nacos client...");
return;
}
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
try {
namingService.deregisterInstance(serviceId, group, registration.getHost(),
registration.getPort(), nacosDiscoveryProperties.getClusterName());
}
catch (Exception e) {
log.error("ERR_NACOS_DEREGISTER, de-register failed...{},",
registration.toString(), e);
}
log.info("De-registration finished.");
}
namingService.deregisterInstance(serviceId, group, registration.getHost(), registration.getPort(), nacosDiscoveryProperties.getClusterName());
交由 NacosNamingService
完成
NacosNamingService#deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)
@Override
public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)
throws NacosException {
Instance instance = new Instance();
instance.setIp(ip);
instance.setPort(port);
instance.setClusterName(clusterName);
// 注销实例
deregisterInstance(serviceName, groupName, instance);
}
NacosNamingService#deregisterInstance(String serviceName, String groupName, Instance instance)
@Override
public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {
clientProxy.deregisterService(serviceName, groupName, instance);
}
其实在上面能看到最终是通过 clientProxy.deregisterService(serviceName, groupName, instance);
完成了服务的注销。
总结
Nacos 通过监听事件完成服务的注册,通过 @PreDestroy
标注的方法完成服务的注销。
剧透下:
- NamingClientProxy 有两种,分别是 NamingHttpClientProxy 以及 NamingGrpcClientProxy,选择哪个进行注册通过 NamingClientProxyDelegate 做了委托(下图的一个判断)。临时实例走 grpc,持久化实例走 httpclient。
- NamingHttpClientProxy 会执行向 Nacos Server 端发送 HTTP 请求的方式注册和注销。
最后
以上就是积极蜡烛为你收集整理的Nacos 服务注册注销源码浅析入口NacosAutoServiceRegistrationAbstractAutoServiceRegistration总结的全部内容,希望文章能够帮你解决Nacos 服务注册注销源码浅析入口NacosAutoServiceRegistrationAbstractAutoServiceRegistration总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复