全网最细的nacos服务端服务注册:没有之一

2024-02-05 00:28

本文主要是介绍全网最细的nacos服务端服务注册:没有之一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

服务端注册入口

BaseRpcServer
image.png
由于有@PostConstrct注解,也就是说在构造方法后会执行,startServer会由它的子类BaseGrpcServer.startServer重写

BaseGrpcServer.startServer

image.png
addServices:
image.png
其中grpcCommonRequestAcceptor和grpcBiStreamRequestAcceptor就是实现了nacos_grpc_service.proto的两个子处理类
public class GrpcRequestAcceptor extends RequestGrpc.RequestImplBase {
�public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestStreamImplBase {

对应nacos_grpc_service.proto中的两个方法处理

service Request {// Sends a commonRequestrpc request (Payload) returns (Payload) {}
}service BiRequestStream {// Sends a biStreamRequestrpc requestBiStream (stream Payload) returns (stream Payload) {}
}

GrpcRequestAcceptor.request

image.png
image.png
这里最终会调用到InstanceRequestHandler.handle方法,不用猜基本上就知道要做什么,实例相关的操作

InstanceRequestHandler.handle

image.png
image.png
最终会调用到EphemeralClientOperationServiceImpl.registerInstance

EphemeralClientOperationServiceImpl.registerInstance

image.png
具体做了几件事:

  1. 从ServiceManger里面通过service来获取service(包含namespace,group,name,ephemeral=true),我们来看一下ServiceManger具体是什么样子的存储结构?

image.png
更加形象的是这样:
image.png

  1. 从ClientManger通过clientId获取Client,这里我们来看一下clientId、ClientManger、Client分别是什么?

ClientId:
image.png
ClientManger: 专门用来管理客户端连接的组件
image.png
Client:客户端信息
上图中connectionBasedClientManger里面的clients属性 ,里面存储的key、value,key为clientId,value为客户端信息,也就是上面的ConnectionBasedClient
image.png

  1. 创建发布信息,并将发布信息放到ConnectionBasedClient中

image.png
将Service和publishInfo放到publishers中,实际的数据如图:
image.png

  1. 发布ClientRegisterServiceEvent�事件,具体需要看看这个事件是由谁来处理,其实很好找,看看这个那个类使用了这个事件就行,最终找到了ClientServcieIndexesManger

ClientServiceIndexesManager.handleClientOperation

image.png
image.png
image.png
这里总结一下做了几件事:

  1. 将service以及clientId放到publisherIndexes中,存储的格式就是<Service,Set>,更加形象的图如图:

image.png

  1. 发布ServiceChangedEvent事件,这个事件最终会被NamingSubscriberServiceV2Impl给处理

NamingSubscriberServiceV2Impl.onEvent

image.png
这里会将事件封装成PushDelayTask,然后使用delayTaskEngine,这里的delayTaskEngine是PushDelayTaskExecute

PushDelayTaskExecuteEngine�.addTask

PushDealyTaskExecuteEngine继承了NacosDelayTaskExecuteEngine,最终会调用到父类的addTask方法
image.png
image.png
image.png
其实这里比较简单,就是把task加入到ConcurrentHashMap里面去,key就是Servcie,value就是pushDelayTask

加入到这个ConcurrentHashMap肯定是要被处理的,那我们看看是在哪里被处理?

  1. NacosDelayTaskExecuteEngine在构造方法里面创建了一个定时调度的线程池,里面有一个被定时调度的任务,每隔100ms被调度执行

image.png
image.png

  1. NacosDelayTaskExecuteEngine.processTask

image.png
遍历上面的concurrentHashMap,然后通过taskkey然后找到处理类,因为我们没有设置,所以这里的NacosTaskProcessor就是子类PushDelayTaskExecuteEnginge里面设置的PushDelayTaskProcessor
image.png

  1. PushDelayTaskProcessor.process

image.png
image.png
这里的NacosExecuteTaskExecuteEngine还是需要详细分析一下

到这里用图总结一下从NamingSubscriberServiceV2Impl.onEvent到此处:
image.png

NacosExecuteTaskExecute.addTask

NacosExecuteTaskExecute.addTask
image.png
逻辑比较简单,先看看它有没有对应的NacosTaskProcessor,实际就是没有的(key没有,默认也没有设置),接下来就直接通过getWorker来处理

image.png
从executeWorkers中取一个TaskExecuteWorker给这个task来执行,所以我们要看一下这个executeWorkers到底是什么?
image.png
这里的TaskExecuteWorker就是一个单线程执行器

TaskExecuteWorker.process

image.png
image.png
又是似曾相识的套路,往queue里面塞东西,那具体在哪里处理的?
里面有内部单线程处理:
image.png
也就说最终还是会调用到传进来task的run方法,看到这里感觉无比的累啊,应该快结束了

到这里也拿一张图总结一下:
image.png

PushExecuteTask.run

image.png
image.png
image.png
image.png
总结一下做了几件事:

  1. 生成推送数据:generatePushData
    1. 通过serviceIndexesManger + service能找到service对应那些clientId

image.png

  1. 通过clientManger+ clientId能找到client对应的发布信息publishers,再通过publishers+service能找到这个service对应的Instance

image.png
我们来看一下实际debug得到的数据:
image.png

  1. 往serviceClusterIndex.put(service, clusters)

image.png

  1. 往serviceDataIndexes.put(service, serviceInfo)

image.png

  1. 推送给目标客户端
    1. getTargetClients: 通过ClientServiceIndexManger+ service来获取这个订阅这个service所有clientId

image.png

  1. 遍历订阅这个service的所有clientId,通过ClientManger+ clientId找到这个客户端,再通过这个客户端的subsribers+ service就能知道这个客户端订阅这个service的详情了

image.png

  1. 最后调用doPushWithCallback往订阅客户端推送数据

这篇关于全网最细的nacos服务端服务注册:没有之一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/679249

相关文章

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

Python FastMCP构建MCP服务端与客户端的详细步骤

《PythonFastMCP构建MCP服务端与客户端的详细步骤》MCP(Multi-ClientProtocol)是一种用于构建可扩展服务的通信协议框架,本文将使用FastMCP搭建一个支持St... 目录简介环境准备服务端实现(server.py)客户端实现(client.py)运行效果扩展方向常见问题结

Nacos注册中心和配置中心的底层原理全面解读

《Nacos注册中心和配置中心的底层原理全面解读》:本文主要介绍Nacos注册中心和配置中心的底层原理的全面解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录临时实例和永久实例为什么 Nacos 要将服务实例分为临时实例和永久实例?1.x 版本和2.x版本的区别

Nacos日志与Raft的数据清理指南

《Nacos日志与Raft的数据清理指南》随着运行时间的增长,Nacos的日志文件(logs/)和Raft持久化数据(data/protocol/raft/)可能会占用大量磁盘空间,影响系统稳定性,本... 目录引言1. Nacos 日志文件(logs/ 目录)清理1.1 日志文件的作用1.2 是否可以删除

SpringCloud使用Nacos 配置中心实现配置自动刷新功能使用

《SpringCloud使用Nacos配置中心实现配置自动刷新功能使用》SpringCloud项目中使用Nacos作为配置中心可以方便开发及运维人员随时查看配置信息,及配置共享,并且Nacos支持配... 目录前言一、Nacos中集中配置方式?二、使用步骤1.使用$Value 注解2.使用@Configur

C#使用MQTTnet实现服务端与客户端的通讯的示例

《C#使用MQTTnet实现服务端与客户端的通讯的示例》本文主要介绍了C#使用MQTTnet实现服务端与客户端的通讯的示例,包括协议特性、连接管理、QoS机制和安全策略,具有一定的参考价值,感兴趣的可... 目录一、MQTT 协议简介二、MQTT 协议核心特性三、MQTTNET 库的核心功能四、服务端(BR

SpringBoot快速搭建TCP服务端和客户端全过程

《SpringBoot快速搭建TCP服务端和客户端全过程》:本文主要介绍SpringBoot快速搭建TCP服务端和客户端全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录TCPServerTCPClient总结由于工作需要,研究了SpringBoot搭建TCP通信的过程

jupyter代码块没有运行图标的解决方案

《jupyter代码块没有运行图标的解决方案》:本文主要介绍jupyter代码块没有运行图标的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录jupyter代码块没有运行图标的解决1.找到Jupyter notebook的系统配置文件2.这时候一般会搜索到

SpringCloud之consul服务注册与发现、配置管理、配置持久化方式

《SpringCloud之consul服务注册与发现、配置管理、配置持久化方式》:本文主要介绍SpringCloud之consul服务注册与发现、配置管理、配置持久化方式,具有很好的参考价值,希望... 目录前言一、consul是什么?二、安装运行consul三、使用1、服务发现2、配置管理四、数据持久化总

Spring Cloud之注册中心Nacos的使用详解

《SpringCloud之注册中心Nacos的使用详解》本文介绍SpringCloudAlibaba中的Nacos组件,对比了Nacos与Eureka的区别,展示了如何在项目中引入SpringClo... 目录Naacos服务注册/服务发现引⼊Spring Cloud Alibaba依赖引入Naco编程s依