概要
此篇部落格重點講述SpringCloudAlibaba的nacos的用戶端是怎麼在啟動的時候,把自己的服務注冊到注冊中心的。
綜述
- SpringcloudAlibaba既然是SpringCloud項目,那麼它必定遵循SpringCloud定義的規範,該規範包括一些注冊服務,下線服務等。
- SpringCloudAlibaba又是一個SpringBoot項目,那麼它肯定也遵循SpringBoot的規範,該規範包括自動裝配的spring.factories
- SpringCloudAlibaba的啟動必然是使用SpringBoot的自動裝配的技術來實作它的自動啟動,相對來說主要是SpringBoot的流程
流程圖
可右鍵下載下傳

步驟
一,maven倉庫位址
項目中引入的是這個jar包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
二,檢視對應的jar包
三,點開jar包,檢視jar包的自動配置檔案
四,看這個檔案
發現了一堆的自動注冊的類。我們現在要看的代碼是服務自動注冊的流程,下列代碼最符合這個意思的是
NacosServiceRegistryAutoConfiguration
五,配置類的代碼
- com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration
SpringCloudAlibaba的NacosClient自動注冊 - 調用構造方法
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
- 這個是調用父類的構造方法 org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry,
AutoServiceRegistrationProperties properties) {
this.serviceRegistry = serviceRegistry;
this.properties = properties;
}
- 順便看看這個的關系圖
SpringCloudAlibaba的NacosClient自動注冊 - 有一個關鍵的實作,那就是ApplicationLIstener,它會在項目啟動的時候調用,我們看看這個方法
SpringCloudAlibaba的NacosClient自動注冊 -
它的父類實作了具體的方法,我們來看看方法具體
監聽web容器啟動完成之後釋出的事件
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
bind(event);
}
- 看bind方法
@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();
}
- 看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方法
/**
* Register the local service with the {@link ServiceRegistry}.
*/
protected void register() {
this.serviceRegistry.register(getRegistration());
}
- com.alibaba.cloud.nacos.registry.NacosServiceRegistry#register
這個類就是在執行個體化的時候傳入的類,那麼當然是調用這個類來完成注冊
@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) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
// rethrow a RuntimeException if the registration is failed.
// issue : https://github.com/alibaba/spring-cloud-alibaba/issues/1132
rethrowRuntimeException(e);
}
}
- 看注冊方法 com.alibaba.nacos.api.naming.NamingService#registerInstance
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
NamingUtils.checkInstanceIsLegal(instance);
String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
if (instance.isEphemeral()) {
BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
beatReactor.addBeatInfo(groupedServiceName, beatInfo);
}
serverProxy.registerService(groupedServiceName, groupName, instance);
}
- 看registerService方法
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName,
instance);
final Map<String, String> params = new HashMap<String, String>(16);
params.put(CommonParams.NAMESPACE_ID, namespaceId);
params.put(CommonParams.SERVICE_NAME, serviceName);
params.put(CommonParams.GROUP_NAME, groupName);
params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
params.put("ip", instance.getIp());
params.put("port", String.valueOf(instance.getPort()));
params.put("weight", String.valueOf(instance.getWeight()));
params.put("enable", String.valueOf(instance.isEnabled()));
params.put("healthy", String.valueOf(instance.isHealthy()));
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
}
看到這裡就不用往下繼續看了,很明顯,這裡建構了一堆的參數。用來發送http網絡請求。伺服器會收到這個請求,把執行個體資料儲存下來