SRPC 框架服务端源码解析

news2024/11/18 3:25:57

0. RPC Context

保存某些必要的上下文信息;

某端独有功能:Client 获取请求成功或失败

1. RPCBuffer

constconstexpr 变量的主要区别是:const 变量的初始化可以被推迟到运行期,constexpr 必须在编译期初始化;所有 constexpr 都是 const

buffer_t 指向实际的数组,代表一个缓存块;再通过链表将各缓存块连接起来;

(1)BUFFER_MODE_NOCOPY 类型的缓存块如何释放?

在代码中,删除或合并时没用对 is_nocopy 进行删除,是否会引发内存泄漏?

规定标记:旧 RPCBuffer 为 B1,新 RPCBuffer 为 B2

在 B1 调用 cut 生成 B2 时,如果当前位置位于某个缓存块的中间位置,那么该缓存块就会由这两个 RPCBuffer 共同管理,注意到在 B2 中管理该缓存块的后半部分,类型为 BUFFER_MODE_NOCOPY ,但在 B1 中管理该缓存块的前半部分,其类型没用改变,仍然为 BUFFER_MODE_GIFT_MALLOC;

显然这种情况要求,B2 先释放后,B1 才能释放,如何保证该要求的实现?

(2)acquire 中申请缓存块时,有极值限制,过大过小都会调整,避免频繁申请内存;

(3)read_back 函数中,offset 绝对值过大时 cur_.firstbegin, secondbegin->buflen, 如果此时调用 internal_fetch 会获取第二块缓存,但应该获取第一块,就会造成问题;

因此需要保证 offset 不会大于当前的 size_ ,如何保证?

2. zero_copy_stream

内部都包装了一个 RPCBuffer 指针;

根据作者的知乎文章,下述两个类是用于序列化和反序列化过程;

2.1 RPCOutputStream

构造时可以指定需要的缓存大小,如果未指定,会按最小的来申请;

(1)Next 结合循环,即内部不断申请缓存块,以填充数据;

// Copy the contents of "infile" to "outfile", using plain read() for
// "infile" but a ZeroCopyOutputStream for "outfile".
int infd = open("infile", O_RDONLY);
int outfd = open("outfile", O_WRONLY);
ZeroCopyOutputStream* output = new FileOutputStream(outfd);

void* buffer;
int size;
while (output->Next(&buffer, &size)) {
  int bytes = read(infd, buffer, size);
  if (bytes < size) {
    // Reached EOF.
    output->BackUp(size - bytes);
    break;
  }
}

delete output;
close(infd);
close(outfd);

由 Protocol Buffers 官网示例可以看出,最后一块内存一般来说会给得多一些,因此只需回退最后一个缓存块,与 RPCBuffer 中 backup 设计吻合;

2.2 RPCInputStream

(1)Next

其中调用了 RPCBuffer 的 fetch方法,结合 while 循环,即不断获取 RPCBuffer 中待读取的缓存块,直到所有缓存块都读取完毕;

// Read in a file and print its contents to stdout.
int fd = open("myfile", O_RDONLY);
ZeroCopyInputStream* input = new FileInputStream(fd);

const void* buffer;
int size;
while (input->Next(&buffer, &size)) {
  cout.write(buffer, size);
}

delete input;
close(fd);

(2)BackUp

理论上,如果内存里有超过一个 message,那么当前 message 解析完整之后,需要回退 count 字节。

这里需要注意一下 RPCBuffer 中的(3)的问题;(即保证不用过度回退)

3. RPCMessage

3.1 SRPCMessage

代表一条消息,message 数据可能是分成数份传递过来的

(1)append 函数,从形参 buf 中接收数据,workflow 收到网络包后会调用该函数;

header 由固定大小的数组接收
meta_bufnew 分配空间,存放 meta 数据
message 数据则放入 RPCBuffer 中

在这里插入图片描述
(2)deserialize

使用接收 message 数据部分的 buf 初始化 RPCInputStream

直接调用 Protobuf 的 ParseFromZeroCopyStream 解析消息

(3)encode(要求 iovec 数组的大小最少为 3);workflow 会在进行网络发送时会被调用

  1. 设置 header
  2. 将 header 数组和 meta_buf 分别填入 iovec 数据结构中(使用两个)
  3. 调用 bufencode 方法,将 message 部分填入 iovec 数据结构中(最少使用一个)

可以合理猜测底层 workflow 会使用 writev 来发送数据

4. rpc_module

4.1 SnowFlake

(1)get_id生成不同的分布式 ID,总位数为 64 位,由以下四部分组成:

timestampgroup_idmachine_idsequence

timestamp 由 std::chrono::steady_clock 产生,单位为 ms,如果在同一 ms 内的申请,由 sequence 进行区分

std::chrono::steady_clock 为单调时钟,两个 tick 之间的时间固定,与钟表上的时间不同(可以是从某个时间点开始的),适合测量间隔;)

sequence 和 last_timestamp 由原子变量维护;

5. 服务器端

5.1 RPCWorker

封装了 请求和相应 Message,及 RPCContext,这些基类指针指向派生类(是 proto 生成类型,基类为 google::protobuf::Message

5.2 RPCService

服务名 name_
内部维护一个哈希表 methods_,key 为方法名,val 为回调函数

(1)add_method 就是将回调函数加入到这个 methods_ 中;

(2)ServiceRPCCallImpl

申请 req 的空间
从 RPCWorker 中接收到的 Message 反序列化出 req( SRPCMessage 中 buf 转化为 EchoRequest 类型)
如果成功解析,调用用户 rpc 函数;

5.2.1 Service

位于服务端;

service Example {
     rpc Echo(EchoRequest) returns (EchoResponse);
};

是由 srpc_generator protobuf 生成的 xxx.srpc.h 文件中,继承自 RPCService;

RPC 服务为 Service 中的纯虚函数,用户需要继承自该类,实现该函数;

(1)Service 的构造函数会设置 name_ 为 Example,调用 RPCService::add_method ,从而注册回调函数(方法名为 Echo,绑定 this 指针结合虚函数动态绑定机制的调用用户实现的函数);

5.2.2 RPCServer

继承自 WFServer

内部维护一个哈希表 service_map,key 为服务名,val 为 RPCService 指针;

(1)add_service 就是在 service_map 中添加 RPCService ;

(2)start 为 WFServer 中的方法,为开启 TCP 服务器;

推测有数据到来,会调用 server_process 函数

(3)server_process

  1. ParseFromArray 解析 RPCMeta;(反序列化,从 meta_buf 转换为 RPCMeta 类型)

  2. 从 RPCMeta 中的解析出 RPCMetaKeyValue 存放到 RPCModuleData 中( map 类型)

  3. module 部分处理(此步看不太懂)

  4. message 数据部分解压缩;

  5. 调用 rpc;

  6. 设置响应状态码

5.2.3 RPCServerTask

(1)message_out ,用来告诉 Workflow 网络层面这次发出的请求内容时啥

  1. 将 EchoResponse 序列化为到 SRPCMessage类型的 buf

  2. 将 SRPCMessage类型的 buf 中的数据进行压缩

  3. 处理 module

  4. 序列化 meta(将 RPCMeta 类型转换为 SRPCMessage 中的字符数组 meta_buf
    RPCMeta 类型也是由 proto 定义生成的类型

  5. 设置状态码,即设置 meta 中的 status_code 属性

6. RPCCompressor

使用了单例模式,局部静态变量初始化

私有构造函数会添加其支持的各种压缩算法;

持有 CompressHandler 的固定大小的数组,每种代表一个压缩算法;

(1)parse_from_compressed,根据给定的类型,调用相关压缩算法的函数

6.1 CompressHandler

封装了一些函数句柄;

7. 客户端部分

由于要放寒假了,之后有时间再看吧;

7.1 RPCClientTask

user_done_ 就是用户设置的 rpc 完成回调函数;

如果使用 rpc 的异步接口,create_rpc_client_task

即调用 RPCClient::create_rpc_client_task,在该函数中会创建 RPCClientTask。

重要参考

作者本人的知乎,对整个流程介绍还是非常清晰的,尤其是对像我这种不懂 workflow 的人

https://zhuanlan.zhihu.com/p/619721187

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1410764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剪映声音克隆;多位滴滴前中高层加入小红书提速商业化;中国和新加坡互免签证

今日精选 • 剪映推出 AI 音色克隆功能&#xff0c;录制 5 秒声音即可完成克隆• 商业化全面提速&#xff0c;多位滴滴前中高层加入小红书• 2 月 9 日起&#xff0c;中国和新加坡互免签证 科技动态 • 夸克上线大模型新产品“AI PPT”&#xff0c;可一键生成提纲、创作 PPT…

消息中间件之RocketMQ(三)

常见问题 1.重复消费 产生的原因是发送消息时采用了多数分布式消息中间件产品提供的最少一次(at least once)的投递保障&#xff0c;对于这个问题最常见的解决方案,就是消息消费端实现业务幂等&#xff0c;只要保持幂等性&#xff0c;不管来多少条重复消息&#xff0c;最后处…

码多多ChatAI智能聊天系统-一款好用的代码编程助手

码多多ChatAI智能聊天系统可以作为一款智能编程助手&#xff0c;帮助程序员提高编程效率&#xff0c;降低开发成本。 产品介绍 码多多ChatAI智能聊天系统是一款基于人工智能技术的编程辅助工具&#xff0c;它通过深度学习算法和大数据分析&#xff0c;为程序员提供智能代码提…

权威的健康养生与医学基础知识科普学习信息汇总

目录 1 关于健康与食物营养的权威网址1.1 世界卫生组织&#xff08;World Health Organization: WHO&#xff09;1.2 美国国家卫生研究院 (National Institutes of Health: NIH)1.3 澳大利亚政府健康门户 (Healthdirect)1.4 国际食品信息委员会 (International Food Informatio…

如何使用宝塔面板配置Nginx反向代理WebSocket(wss)

本章教程&#xff0c;主要介绍一下在宝塔面板中如何配置websocket wss的具体过程。 目录 一、添加站点 二、申请证书 三、配置代理 1、增加配置内容 2、代理配置内容 三、注意事项 一、添加站点 二、申请证书 三、配置代理 1、增加配置内容 map $http_upgrade $connection_…

【GitHub项目推荐--不错的 Electron开源项目】【转载】

eDEX-UI&#xff1a;超炫酷终端工具 eDEX-UI 是一款跨平台基于 Electron 的炫酷终端工具。好莱坞级别的终端使用体验&#xff0c;拥有漂亮的启动动画、浮夸的音效&#xff0c;还能够直观地展示文件目录、系统资源、网络等信息。支持实时系统和网络监控、触摸式显示器&#xff…

AI Toolkit软件安装教程(附软件下载地址)

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; AI Toolkit是一款卓越的人工智能软件&#xff0c;专为企业和个人提供一体化的解决方案&#xff0c;助力其工作流程高效运转。该软件套件融合了多种顶…

【公务员】图形推理技巧

位置规律 图形特征&#xff1a; 图形组成相同&#xff0c;优先考虑位置规律。 详细技巧&#xff1a; 样式规律 图形特征&#xff1a; 图形组成相似&#xff0c;优先考虑样式规律。 详细技巧&#xff1a; 形式技巧加法1、直接叠加2、☆规则运算&#xff1a;外轮廓与分割区域…

OpenCV笔记之图像处理中遮罩和掩模的关系

OpenCV笔记之图像处理中遮罩和掩模的关系 code review 文章目录 OpenCV笔记之图像处理中遮罩和掩模的关系1.遮罩详解遮罩的创建遮罩的应用遮罩的主要应用遮罩的类型如何创建遮罩遮罩在图像处理中的应用方式 2.遮罩和掩模的关系 1.遮罩详解 在图像处理中&#xff0c;遮罩&#…

Linux/Doctor

Enumeration nmap 已知目标开放了22,80,8089端口&#xff0c;扫描详细情况如下 可以看到对外开放了22,80,8089三个端口 TCP/80 SSTI 访问80端口&#xff0c;有一个infodoctors.htb的电子邮件&#xff0c;点击其他的也没有什么反应&#xff0c;猜测有可能需要域名访问 在/et…

进程(三)进程间的切换、环境变量

文章目录 进程间的切换Linux2.6内核进程调度队列一个CPU拥有一个runqueue优先级活跃进程过期队列active指针和expired指针 环境变量基本概念常见环境变量查看环境变量的方法测试PATH测试HOME和环境变量相关的命令通过代码如何获取环境变量通过系统调用获取环境变量 进程间的切换…

错误票据-蓝桥杯

思路&#xff1a; 其实只是排序一下&#xff0c;然后遍历&#xff0c;如果两个值差2&#xff0c;则输出两个值的平均数&#xff0c;如果两个数差值为0 &#xff0c;那么则这个值就是重复的值 代码&#xff1a; #include <iostream> #include<vector> #include&l…

第二篇【传奇开心果短博文系列】鸿蒙开发技术点案例示例:添加组件和事件处理

传奇开心果短博文系列 系列短博文目录鸿蒙开发技术点案例示例短博文系列 短博文目录一、前言二、添加组件和事件处理示例代码三、补全其余组件事件处理示例代码 系列短博文目录 鸿蒙开发技术点案例示例短博文系列 短博文目录 一、前言 有一必然会有二&#xff0c;有了第一个…

Java项目:基于SSM框架实现同城蔬菜配送管理系统(SSM+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm825基于SSM框架实现同城蔬菜配送管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&…

小程序系列--12使用 npm 包

一、Vant Weapp 1. 什么是 Vant WeappVant Weapp 是有赞前端团队开源的一套小程序 UI 组件库&#xff0c;助力开发者快速搭建小程序应用。它所使用的是 MIT 开源许可协议&#xff0c;对商业使用比较友好。 官方文档地址 https://youzan.github.io/vant-weapp 2. 安装 Vant 组…

《WebKit 技术内幕》学习之六(1): CSS解释器和样式布局

《WebKit 技术内幕》之六&#xff08;1&#xff09;&#xff1a;CSS解释器和样式布局 CSS解释器和规则匹配处于DOM树建立之后&#xff0c;RenderObject树之前&#xff0c;CSS解释器解释后的结果会保存起来&#xff0c;然后RenderObject树基于该结果来进行规范匹配和布局计算。当…

Unity 组合模式(实例详解)

文章目录 示例1&#xff1a;Unity中的图形界面元素组合示例2&#xff1a;Unity中的游戏对象层级组合示例3&#xff1a;Unity中的场景图节点组合示例4&#xff1a;Unity中的场景管理组合示例5&#xff1a;Unity中的角色技能树组合 在Unity中&#xff0c;组合模式&#xff08;Com…

哈希的基本概念(开散列和闭散列)(附代码)

哈希 哈希概念哈希冲突哈希函数常见的哈希函数 哈希冲突的解决闭散列开散列 哈希概念 传统的查找函数&#xff0c;搜索的效率取决于比较的次数。而hash算法&#xff1a;在理想情况下&#xff0c;可以不经过任何比较&#xff0c;一次就能得到要搜索的结果。 存储结构&#xff1…

四、MyBatis 动态语句

本章概要 动态语句需求和简介if 和 where 标签set 标签trim 标签(了解)choose/when/otherwise 标签foreach 标签sql 片段 4.1 动态语句需求和简介 经常遇到很多按照很多查询条件进行查询的情况&#xff0c;比如智联招聘的职位搜索等。其中经常出现很多条件不取值的情况&#…

电脑监控系统:企业网络安全解决方案

在当今数字化的世界里&#xff0c;企业的网络安全已经成为一项至关重要的任务。电脑监控系统作为一种有效的解决方案&#xff0c;正在被越来越多的企业所采用。 电脑监控系统是一种集成了多种安全功能的综合性解决方案&#xff0c;旨在为企业提供全面的网络安全防护。该系统能够…