看了Eureka系列、Ribbon系列、Feign系列、Zuul系列,我相信大家應該知道怎麼找到看原始碼的入口了,一個是需要用的註解,一個是spring.factories。我們還是從註解先來。
@EnableDiscoveryClient
這個註解做了兩件事,一個是import了EnableDiscoveryClientImportSelector,另外一個就是預設autoRegister為true,開啟自動註冊。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
boolean autoRegister() default true;
}
EnableDiscoveryClientImportSelector的selectImports方法,透過上面的autoRegister來判斷,如果為true,則import了AutoServiceRegistrationConfiguration,如果為false,pring.cloud.service-registry.auto-registration.enabled設定為false。這個引數決定了是否引入自動註冊。
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 其他略
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 {
// 其他略
// spring.cloud.service-registry.auto-registration.enabled設定為false
map.put("spring.cloud.service-registry.auto-registration.enabled", false);
// 其他略
}
return imports;
}
NacosServiceAutoConfiguration
註解的部分看完了,我們開始看spring.factories。首先是NacosServiceAutoConfiguration。
這裡只載入了NacosServiceManager,是service核心管理類,NamingService就是他管理的。
NacosDiscoveryAutoConfiguration
這個是用於服務發現的,他載入了兩個類,NacosDiscoveryProperties和NacosServiceDiscovery。
NacosDiscoveryProperties是配置類,我們配置註冊中心的資訊就是在這裡配置。
NacosServiceDiscovery主要是用於服務發現。
NacosServiceRegistryAutoConfiguration
NacosServiceRegistryAutoConfiguration,這個是用於自動註冊的。
我們看到他上面的註解資訊,@AutoConfigureAfter
確保AutoServiceRegistrationConfiguration先載入,然後判斷spring.cloud.service-registry.auto-registration.enabled是否為true,為true才可以載入。所以上面@EnableDiscoveryClient的autoRegister如果設定為false,則不載入。
因為spring.cloud.service-registry.auto-registration.enabled預設是true的,所以@EnableDiscoveryClient其實不引入,也是可以載入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
這個類會載入NacosServiceRegistry、NacosRegistration、NacosAutoServiceRegistration。NacosServiceRegistry、NacosRegistration會注入到NacosAutoServiceRegistration。
NacosServiceRegistry主要用於註冊、取消註冊。
NacosRegistration是當前例項的資訊,比如例項名稱、例項id、埠、ip等。
NacosAutoServiceRegistration繼承了NacosAutoServiceRegistration,NacosAutoServiceRegistration又繼承了AbstractAutoServiceRegistration。AbstractAutoServiceRegistration實現了ApplicationListener<WebServerInitializedEvent>介面,透過WebServerInitializedEvent就知道了,當tomcat啟動成功後,會呼叫onApplicationEvent(WebServerInitializedEvent event)方法。這個方法會實現註冊操作,後面再來講解。
NacosDiscoveryClientConfiguration
這裡載入了兩個類,DiscoveryClient和NacosWatch。
DiscoveryClient主要用於示例獲取和服務獲取。
NacosWatch實現了SmartLifecycle介面,所以會呼叫start和stop方法。
start方法主要是加入NamingEvent監聽、獲取NamingService、註冊監聽、釋出HeartbeatEvent事件。
@Override
public void start() {
// 啟動的時候,加入NamingEvent監聽
if (this.running.compareAndSet(false, true)) {
EventListener eventListener = listenerMap.computeIfAbsent(buildKey(),
event -> new EventListener() {
@Override
public void onEvent(Event event) {
// 更新本地的Instance
if (event instanceof NamingEvent) {
List<Instance> instances = ((NamingEvent) event)
.getInstances();
Optional<Instance> instanceOptional = selectCurrentInstance(
instances);
instanceOptional.ifPresent(currentInstance -> {
resetIfNeeded(currentInstance);
});
}
}
});
// 獲取NamingService
NamingService namingService = nacosServiceManager
.getNamingService(properties.getNacosProperties());
try {
// 註冊監聽
namingService.subscribe(properties.getService(), properties.getGroup(),
Arrays.asList(properties.getClusterName()), eventListener);
}
catch (Exception e) {
log.error("namingService subscribe failed, properties:{}", properties, e);
}
//釋出HeartbeatEvent事件
this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(
this::nacosServicesWatch, this.properties.getWatchDelay());
}
}