Nacos源码 版本1.4.1
客户端源码
Nacos源码整合进spring是从spring.factory开始
image.png
一般整合源码都是auto字样的类,整合的
这里就是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(
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(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);
}
}
往容器中存放了三个bean NacosServiceRegistry NacosRegistration
NacosAutoServiceRegistration
NacosAutoServiceRegistration的继承图
image.png
这里可以看到实现了ApplicationListener,spring的事件监听
那我们就看一下,监听的事件,父类AbstractAutoServiceRegistration的onApplicationEvent方法
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
bind(event);
}
注意bind方法
看一下bind之后的调用链
bind(WebServerInitializedEvent event)
-->this.start();
-->AbstractAutoServiceRegistration#start
-->registerManagement();
-->this.serviceRegistry.register(registration);
-->NacosServiceRegistry#
-->namingService.registerInstance(serviceId, group, instance);
-->NacosNamingService#registerInstance(String serviceName, String groupName, Instance instance)
--> serverProxy.registerService(groupedServiceName, groupName, instance);
-->NamingProxy#registerService(String serviceName, String groupName, Instance instance)
registerService(String serviceName, String groupName, Instance instance)方法
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()));
//向nacos服务端注册
// UtilAndComs.nacosUrlInstance /nacos/v1/ns/instance 服务端http地址
//params参数
//post类型
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
}
上面提到的params是如何被赋值的
NacosServiceRegistry#register(Registration registration)方法
Instance instance = getNacosInstanceFromRegistration(registration);
点进getNacosInstanceFromRegistration方法发现,就是最开始注册的三个bean之一
NacosServiceRegistry,获取配置文件中的属性
WebServerInitializedEvent事件是如何被推送的,大家可以断点,查看一下调用栈,会发现是spring的核心方法中的最后一个finishRefresh()方法,推送的事件.
讲解了客户端如何注册服务端的代码流程.
客户端是如何拉去客户端列表的
image.png
image.png
那我们在看看NacosWatch类
会发现该类实现了SmartLifecycle接口,就是在bean都加载完成时候,会调用start方法
Start方法中有下面这段代码
namingService.subscribe(properties.getService(), properties.getGroup(),
Arrays.asList(properties.getClusterName()), eventListener);
调用链
NacosNamingService#subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)
--> hostReactor.subscribe(NamingUtils.getGroupedName(serviceName, groupName), StringUtils.join(clusters, ","),listener);
-->HostReactor#subscribe(String serviceName, String clusters, EventListener eventListener)
-->getServiceInfo(serviceName, clusters);
-->HostReactor#getServiceInfo(final String serviceName, final String clusters)
--> scheduleUpdateIfAbsent(serviceName, clusters);
-->HostReactor#scheduleUpdateIfAbsent
-->ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
addTask方法,可以看到是定时任务线程池 其中DEFAULT为1000单位毫秒,1秒钟
public synchronized ScheduledFuture<?> addTask(UpdateTask task) {
return executor.schedule(task, DEFAULT_DELAY, TimeUnit.MILLISECONDS);
}
定时任务,那我们是要关心UpdateTask的run方法的
其中updateService(serviceName, clusters);方法就是从服务端获取服务列表的
发现最终调用服务端接口的代码
public String queryList(String serviceName, String clusters, int udpPort, boolean healthyOnly)
throws NacosException {
final Map<String, String> params = new HashMap<String, String>(8);
params.put(CommonParams.NAMESPACE_ID, namespaceId);
params.put(CommonParams.SERVICE_NAME, serviceName);
params.put("clusters", clusters);
params.put("udpPort", String.valueOf(udpPort));
params.put("clientIP", NetUtils.localIP());
params.put("healthyOnly", String.valueOf(healthyOnly));
//在注册源码的时候,我们就看到了repApi方法,这个方法就会发送http请求
//路径就是/instance/list
return reqApi(UtilAndComs.nacosUrlBase + "/instance/list", params, HttpMethod.GET);
}
网友评论