目录
2.查看EnableDiscoveryClientImportSelector
3.查看AutoServiceRegistrationConfiguration配置类
4.idea右击类文件,点击Find Usages(快捷键alt+f7),查看AutoServiceRegistrationProperties类的引用
5.Nacos的服务注册与发现的自动配置NacosDiscoveryAutoConfiguration
6.AbstractAutoServiceRegistration实现事件监听,完成服务自动注册
前言
基于Greenwich.RELEASE版本,了解@EnableDiscoveryClient发生了什么
Nacos服务自动注册总结
nacos实现spring cloud commons包下服务实例注册与撤销的标准,在配置类标有@EnableDiscoveryClient时,导入nacos服务自动注册的自动配置,采用事件监听方式,在spring上下文刷新和web服务准备好后,监听WebServerInitializedEvent 事件,
最终执行了nacosNacosServiceRegistry的注册方法,完成了服务实例的注册。
Nacos服务自动注册过程源码分析
1.@EnableDiscoveryClient
/**
* Annotation to enable a DiscoveryClient implementation.
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/**
* If true, the ServiceRegistry will automatically register the local server.
*/
boolean autoRegister() default true;
}
1.激活DiscoveryClient类的实现
2.导入配置类EnableDiscoveryClientImportSelector
3.默认开启自动注册服务
2.查看EnableDiscoveryClientImportSelector
导入了标注有@EnableDiscoveryClient的配置类,并且根据属性autoRegister,默认导入了
org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration配置类
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
String[] imports = super.selectImports(metadata);
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
boolean autoRegister = attributes.getBoolean("autoRegister");
if (autoRegister) {
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
imports = importsList.toArray(new String[0]);
} else {
Environment env = getEnvironment();
if(ConfigurableEnvironment.class.isInstance(env)) {
ConfigurableEnvironment configEnv = (ConfigurableEnvironment)env;
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.service-registry.auto-registration.enabled", false);
MapPropertySource propertySource = new MapPropertySource(
"springCloudDiscoveryClient", map);
configEnv.getPropertySources().addLast(propertySource);
}
}
return imports;
}
.....省略其他
}
3.查看AutoServiceRegistrationConfiguration配置类
主要作用是开启了服务的自动注册属性,并启用了AutoServiceRegistrationProperties属性文件,是开启服务注册的关键性文件。
@Configuration
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationConfiguration {
}
4.idea右击类文件,点击Find Usages(快捷键alt+f7),查看AutoServiceRegistrationProperties类的引用
可以看见主要是导入两个配置类
AutoServiceRegistrationAutoConfiguration
NacosDiscoveryAutoConfiguration
其中NacosDiscoveryAutoConfiguration是在
AutoServiceRegistrationProperties和AutoServiceRegistrationAutoConfiguration装配后,进行初始化的
其中AutoServiceRegistrationAutoConfiguration,主要是在AutoServiceRegistration和AutoServiceRegistrationProperties两个bean初始化完后,判断是否成功注入,如果失败抛出错误。其中AutoServiceRegistration是spring-cloud-common包下,作为服务注册与发现的基类。
@Configuration
@Import(AutoServiceRegistrationConfiguration.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationAutoConfiguration {
@Autowired(required = false)
private AutoServiceRegistration autoServiceRegistration;
@Autowired
private AutoServiceRegistrationProperties properties;
@PostConstruct
protected void init() {
if (autoServiceRegistration == null && this.properties.isFailFast()) {
throw new IllegalStateException("Auto Service Registration has been requested, but there is no AutoServiceRegistration bean");
}
}
}
查看AutoServiceRegistration源码,可以看出eureka和nacos服务的注册与发现都是继承了AutoServiceRegistration
5.Nacos的服务注册与发现的自动配置NacosDiscoveryAutoConfiguration
主要是注入了三个bean,分别是NacosServiceRegistry ,NacosRegistration ,NacosAutoServiceRegistration
@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class })
public class NacosDiscoveryAutoConfiguration {
//实现了springclou commons包服务注册与撤销的接口的bean,可以进行服务注册与撤销
@Bean
public NacosServiceRegistry nacosServiceRegistry(
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(nacosDiscoveryProperties);
}
//nacos管理端服务的配置,主要是配置文件managment.下属性的配置
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosRegistration nacosRegistration(
NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
return new NacosRegistration(nacosDiscoveryProperties, context);
}
//初始化nacos服务自动注册的bean
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
}
其中NacosAutoServiceRegistration类是对nacos的自动服务注册进行初始化的。
而且它继承的抽象方法AbstractAutoServiceRegistration实现了ApplicationListener<WebServerInitializedEvent>
的监听(在spring上下文环境刷新和web server准备好后,便接收到监听事件WebServerInitializedEvent)
6.AbstractAutoServiceRegistration实现事件监听,完成服务自动注册
下面抽取AbstractAutoServiceRegistration关键的几个方法
执行顺序:
1.在spring上下文环境刷新和web server准备好后,便发布WebServerInitializedEvent事件
2,AbstractAutoServiceRegistration接收监听事件,执行了bind(event)方法
3.在bind方法中执行了this.start();
4.在start方法中,
进行服务实例预注册监听事件的发布
NacosServiceRegistry的服务注册
服务注册后事件的发布
5.register()方法最终调用NacosServiceRegistry的register(Registration registration)方法进行服务实例的注册
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
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());
this.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);
}
}