当前位置:网站首页>[Happy Qixi Festival] How does Nacos realize the service registration function?
[Happy Qixi Festival] How does Nacos realize the service registration function?
2022-08-04 23:24:00 【Step Ulster】
today is a good day,祝大家七夕快乐.
many subscriptions 《微服务核心技术》 The readers of the column said in a private message in the background:看NacosNo idea when source code,In interviews, you are always asked for details.
Then in the next few days,Let's analyze it step by stepNacos的源码以及NacosThe core functions and mechanisms of,and proceed to write a registry,To help you better understand distributed middleware.
大家都知道Nacos有两大模块:注册中心和配置中心.
那么NacosHow to realize the service registration function of the registry??我们来一探究竟.
在SpringBootunder the base,Whenever we introduce a new adaptation component,You should have a look under this component/META-INF/spring.factories文件,上一篇文章《注解@EnableAutoConfiguration的作用以及如何使用》提到,@SpringBootApplication会自动加载/META-INF/spring.factories文件.

跟进NacosServiceRegistryAutoConfiguration,This class is mainly to complete the service registration function, etc..

@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 {
...
...
...
// service registry corebean
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
}
跟进NacosAutoServiceRegistration
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
跟进super【AbstractAutoServiceRegistration】
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry,
AutoServiceRegistrationProperties properties) {
this.serviceRegistry = serviceRegistry;
this.properties = properties;
}
在这个类下,A monitoring method,This is the core of service registration method.
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
// The core method of service registration
bind(event);
}
Then there is a listening event,there should be a published event,So where is the event posted??
事件是在WebServerStartStopLifecycle#start时发布的
springCore methods during container startup:finishRefresh(),Let's take a look at this method,算了,I'll write a special…移步《Spring源码之finishRefresh()》
SpringApplication#runCore method during startup:
finishRefresh()getLifecycleProcessor().onRefresh();
WebServerStartStopLifecycle(实现SmartLifecycle接口)会发布 ServletWebServerInitializedEvent事件.
NacosAutoServiceRegistration的onApplicationEvent方法处理WebServerInitializedEvent事件.
@Override
public void start() {
this.webServer.start();
this.running = true;
this.applicationContext
.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
}
Know how it was released,我们来看一下AbstractAutoServiceRegistration#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();
}
跟进this.start()

跟进register(),几经辗转,我们来到NacosServiceRegistry#register

跟进namingService.registerInstance(serviceId, group, instance);,我们来到NacosNamingService#registerInstance,我们重点关注一下

跟进NamingProxy#registerService,Assemble client information and send a request to the server.
由此可见,The request for service registration isPOST,请求路径是/nacos/v1/ns/instance
public static String webContext = "/nacos";
public static String nacosUrlBase = webContext + "/v1/ns";
public static String nacosUrlInstance = nacosUrlBase + "/instance";
根据上述结论,We can find the correspondingAPI接口:InstanceController#register
@CanDistro
@PostMapping
@Secured(action = ActionTypes.WRITE)
public String register(HttpServletRequest request) throws Exception {
final String namespaceId = WebUtils
.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
NamingUtils.checkServiceNameFormat(serviceName);
final Instance instance = HttpRequestInstanceBuilder.newBuilder()
.setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();
// 跟进
getInstanceOperator().registerInstance(namespaceId, serviceName, instance);
NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(), "",
false, namespaceId, NamingUtils.getGroupName(serviceName), NamingUtils.getServiceName(serviceName),
instance.getIp(), instance.getPort()));
return "ok";
}
跟进getInstanceOperator().registerInstance(namespaceId, serviceName, instance);
InstanceOperatorServiceImpl#registerInstance
@Override
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
com.alibaba.nacos.naming.core.Instance coreInstance = parseInstance(instance);
// 跟进
serviceManager.registerInstance(namespaceId, serviceName, coreInstance);
}
跟进serviceManager.registerInstance(namespaceId, serviceName, coreInstance);
ServiceManager#registerInstance
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
NamingUtils.checkInstanceIsLegal(instance);
// 跟进
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
Service service = getService(namespaceId, serviceName);
checkServiceIsNull(service, namespaceId, serviceName);
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
跟进createEmptyService(namespaceId, serviceName, instance.isEphemeral());
最后我们来到ServiceManager#createServiceIfAbsent
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster)
throws NacosException {
Service service = getService(namespaceId, serviceName);
//return if service already exists
if (service != null) {
return;
}
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
service.setLastModifiedMillis(System.currentTimeMillis());
service.recalculateChecksum();
if (cluster != null) {
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
// 跟进
putServiceAndInit(service);
if (!local) {
addOrReplaceService(service);
}
}
跟进putServiceAndInit(service);
private void putServiceAndInit(Service service) throws NacosException {
// 跟进
putService(service);
service = getService(service.getNamespaceId(), service.getName());
service.init();
consistencyService
.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
consistencyService
.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJson());
}
跟进putService(service);
public void putService(Service service) {
if (!serviceMap.containsKey(service.getNamespaceId())) {
// Store client information in server memory
serviceMap.putIfAbsent(service.getNamespaceId(), new ConcurrentSkipListMap<>());
}
serviceMap.get(service.getNamespaceId()).putIfAbsent(service.getName(), service);
}
再看一眼这个serviceMap的定义
/** * Map(namespace, Map(group::serviceName, Service)). */
private final Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
来吧,总结一下吧,It is roughly divided into these steps:
- 在
Spring启动时,先发布Nacos服务注册的事件 - 实例化
NacosCore class for service registrationNacosAutoServiceRegistration,并监听事件 - 监听到事件之后,对事件进行处理,封装
Nacos客户端信息,并发送API请求到Nacos服务端接口 - 服务端接收到请求之后,save data to initialized
ConcurrentHashMap中,One-time service registration
接下来,Let's analyze it step by stepNacosThe other core mechanism,and handwritten a registry,Let everyone better understand these distributed middleware.
边栏推荐
- Will we still need browsers in the future?(feat. Maple words Maple language)
- 2022年华数杯数学建模
- 轮播图动态渲染
- I was rejected by the leader for a salary increase, and my anger rose by 9.5K after switching jobs. This is my mental journey
- 对“为什么一些程序员很傲慢”的解读
- 【字符串函数内功修炼】strcpy + strcat + strcmp(一)
- 2022/8/4 树上差分+线段树
- 地面高度检测/平面提取与检测(Fast Plane Extraction in Organized Point Clouds Using Agglomerative Hierarchical Clu)
- Controller层代码这么写,简洁又优雅!
- 应用联合、体系化推进。集团型化工企业数字化转型路径
猜你喜欢
![[Cultivation of internal skills of string functions] strcpy + strcat + strcmp (1)](/img/b6/5a1c8b675dc7f67f359c25908403e1.png)
[Cultivation of internal skills of string functions] strcpy + strcat + strcmp (1)

uniapp 分享功能-分享给朋友群聊朋友圈效果(整理)

MySQL基础篇【聚合函数】

安全软件 Avast 与赛门铁克诺顿 NortonLifeLock 合并案获英国批准,市值暴涨 43%

逆序对的数量

轮播图动态渲染

Basic web in PLSQL

零基础如何入门软件测试?再到测开(小编心得)

文献阅读十——Detect Rumors on Twitter by Promoting Information Campaigns with Generative Adversarial Learn

truffle
随机推荐
【无标题】
[Paper Notes KDD2021] MixGCF: An Improved Training Method for Graph Neural Network-based Recommender Systems
被领导拒绝涨薪申请,跳槽后怒涨9.5K,这是我的心路历程
应用联合、体系化推进。集团型化工企业数字化转型路径
功耗控制之DVFS介绍
CS8416国产替代DP8416 数字音频接收器
MySQL基础篇【聚合函数】
365天深度学习训练营-学习线路
容联云发送短信验证码
typeScript-部分应用函数
Web安全开发 | 青训营笔记
MYS-6ULX-IOT 开发板测评——使用 Yocto 添加软件包
MySQL的JSON 数据类型2
亿流量大考(3):不加机器,如何抗住每天百亿级高并发流量?
【3D建模制作技巧分享】ZBrush如何使用Z球
[QNX Hypervisor 2.2用户手册]10.5 vdev ioapic
uniapp horizontal tab (horizontal scrolling navigation bar) effect demo (organization)
truffle
Controller层代码这么写,简洁又优雅!
【3D建模制作技巧分享】ZBrush模型如何添加不同材质