无论是将服务注册到哪种服务注册中心,服务注册的时机都是在AbstractApplicationContext#finishRefresh()方法中;即Spring容器加载完成、Web服务启动之后;
从SpringCloud规范来看,Spring-cloud-common包定义了一套服务注册、发现的规范;服务注册逻辑在ServiceRegistry类中;
package org.springframework.cloud.client.serviceregistry;
/**
* Contract to register and deregister instances with a Service Registry.
*
* @param registration meta data
* @author Spencer Gibb
* @since 1.2.0
*/
public interface ServiceRegistry<R extends Registration> {
/**
* Registers the registration. A registration typically has information about an
* instance, such as its hostname and port.
* @param registration registration meta data
*/
void register(R registration);
/**
* Deregisters the registration.
* @param registration registration meta data
*/
void deregister(R registration);
/**
* Closes the ServiceRegistry. This is a lifecycle method.
*/
void close();
/**
* Sets the status of the registration. The status values are determined by the
* individual implementations.
* @param registration The registration to update.
* @param status The status to set.
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
*/
void setStatus(R registration, String status);
/**
* Gets the status of a particular registration.
* @param registration The registration to query.
* @param The type of the status.
* @return The status of the registration.
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
*/
<T> T getStatus(R registration);
}
从SpringBoot自动装配来看,spring-cloud-netflix-eureka-client
包中有一个自动装配类EurekaClientAutoConfiguration
;
其中使用@Bean注入一个类EurekaAutoServiceRegistration
,它实现了SmartLifecycle接口
当Spring容器初始化完成之后会执行所有SmartLifecycle#start()方法,链路如下:
进而走到EurekaAutoServiceRegistration#start()方法中;
其中的serviceRegistry.register()
负责服务注册到服务注册中⼼Eureka。Eureka中EurekaServiceRegistry
类实现了ServiceRegistry
接口,因此Eureka服务注册的入口为EurekaServiceRegistry#register()方法;
@Override
public void register(EurekaRegistration reg) {
maybeInitializeClient(reg);
if (log.isInfoEnabled()) {
log.info("Registering application "
+ reg.getApplicationInfoManager().getInfo().getAppName()
+ " with eureka with status "
+ reg.getInstanceConfig().getInitialStatus());
}
reg.getApplicationInfoManager()
.setInstanceStatus(reg.getInstanceConfig().getInitialStatus());
reg.getHealthCheckHandler().ifAvailable(healthCheckHandler -> reg
.getEurekaClient().registerHealthCheck(healthCheckHandler));
}
从SpringBoot自动装配来看,spring-cloud-alibaba-nacos-discovery
包中有一个自动装配类NacosServiceRegistryAutoConfiguration
;NacosServiceRegistryAutoConfiguration中会使用@Bean
注解装配NacosAutoServiceRegistration
类;
public class NacosServiceRegistryAutoConfiguration {
@Bean
public NacosServiceRegistry nacosServiceRegistry(
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(nacosDiscoveryProperties);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
....
}
NacosAutoServiceRegistration
间接实现了ApplicationListener
接⼝;
其会监听Web服务初始化完成事件WebServerInitializedEvent
;
在Spring生命周期中,上下文刷新完成阶段,即finishRefresh()方法中会执行所有SmartLifecycle#start()方法;
WebServerStartStopLifecycle实现了SmartLifecycle接口,进而走到WebServerStartStopLifecycle#start()方法,其中会发布Servlet服务初始化完成事件ServletWebServerInitializedEvent
。
ServletWebServerInitializedEvent是WebServerInitializedEvent的子类。所以监听WebServerInitializedEvent的ApplicationListener可以监听到ServletWebServerInitializedEvent。
NacosAutoServiceRegistration的父类AbstractAutoServiceRegistration中基于ApplicationListener#onApplicationEvent()监听到事件;
然后走到NacosAutoServiceRegistration#register()方法开始做服务注册;
最终会走到ServiceRegistry
接口的register(R registration)
⽅法将服务注册到注册中⼼。Nacos中NacosServiceRegistry
类实现了ServiceRegistry
接口。
从Eureka和Nacos做服务注册的入口来看,有两种方式让我们去做服务注册。
此外,还要遵循spring-cloud-common定义的规范,自定义服务注册的入口类一定要是ServiceRegistry
接口的实现类。