RPC原理与FastRPC实现

article/2025/9/26 19:00:44

0. 起因

最近看文档,发现一些组件是通过FastRPC来进行沟通的,并且偶尔看到某些场景下在FastRPC上的时间消耗好像也蛮可观,恰好FastRPC是开源的,因此决定看看FastRPC具体的实现。

1. RPC简介

当初在学Java的时候,初遇RMI(Remote Method Invocation),感觉这是一个非常神奇的东西,竟然可以调用别的机器上的方法!多么好奇这是怎么实现的。后来渐渐明白,其实RMI就是个RPC的另一个名字。那么,RPC的原理是什么呢?
RPC全称Remote Procedure Call(远程过程调用),所谓远程,就是执行的例程(routine)位于另一个地址空间(关于地址空间的介绍可以参阅之前的文章——冰山之下:使用new申请内存的背后
简单说可以认为地址空间就是进程),通常情况下是另一台机器。如图1所示,RPC框架为调用者提供一个代理,这个代理中的方法和远程例程一一对应。当调用者调用了代理的一个方法后,代理通过一种客户端——服务器的方式来,将函数签名、参数等封装成一个网络请求,发送给服务器。服务器接收到请求后通过解析获得函数签名、参数等信息,通过查表获取到目标例程地址,调用该例程并将参数传递给它。例程计算完成后,将结果通过网络返回到代理,代理将服务器返回的结果稍加处理,成为调用者可以理解的数据格式,最终返回到调用者。客户端和服务器的沟通细节是通过RPC框架来实现的,数据的序列化和反序列化、网络请求与答复等细节是隐藏的,对于调用者来说,它并不知道它调用的方法来对数据的处理到底是自己的地址空间进行还是在别的地址空间进行。
举个栗子:你到一家餐厅吃饭,店里有一个服务员为你服务。你点完菜之后,服务员就走进了后厨。但是,服务员并不是直接将你点的菜告诉他们店里的厨师,相反的,他打电话到别的店点了外卖,外卖到了之后他将饭菜重新装盘,然后给你端了上来。但是你是不知道这个细节的,在你看来,这次吃饭和以往的任何一次没有区别,服务员端上的饭菜在哪里做的你是不知道的,你和平常一样点了菜然后菜就上了,你并不需要自己去关心怎么找到外卖电话,怎么将饭菜装盘。你只管点菜和吃,除了可能等的时间比以往略久,没有任何区别。这个栗子中,服务员就扮演着RPC 中代理的角色,你就是调用者,外卖店就是服务器。

Fig 1 RPC internal

情况就是这么个情况,但是由于RPC只是一种实现方法,并没有形成标准,因此有着很多不同的实现,比如gRPC、Dubbo、Thrift和FastRPC等。对于如何进行序列化和反序列化、如何通信,不同的框架有着不同的实现。

2. FastRPC简介

FastRPC是一个XML-RPC协议的实现,它的特点是有多种数据序列化方式可选:二进制、JSON、XML以及Base64,因为它使用HTTP协议作为载体,通过HTTP的头的数据格式协商字段很容易知道数据的格式。

FastRPC相对与其他框架来说非常简单,代码主要就三部分:客户端实现、服务端实现以及数据序列化与反序列化的实现。也是因为它太简单了,它并没有涉及到鉴权等方面的内容,这些需要自己去考虑。但是对于了解一个RPC框架的具体实现已经足够了。

3. FastRPC调用流程

RPC分为两部分:运行在本地址空间的客户端部分以及运行在其他地址空间的服务器部分。下面就来看看FastRPC对于着两部分的实现。

3.1. FastRPC Server调用流程

FastRPC Server的实现如图2所示,其工作流程如下:

  1. 将客户端可以调用的例程依次进行注册,存放到一个注册表,其实就是一个以函数名为键、函数地址为值的一个字典;
  2. 例程注册完成后,开始启动对特定的端口的监听;
  3. 当有请求到达后,通过HTTP的头确定内容的序列化格式,调用对应的反序列化方法对数据进行解析。
  4. 解析完成获得函数名和参数,通过查表或取到函数地址,调用函数并将参数传入;
  5. 函数返回后通过将数据返回请求者。

整个过程非常简单。
Fig 2 FastRPC Server

3.2. FastRPC Client的调用流程

FastRPC Client的实现如图3所示,其工作流程如下:

  1. 首先进行链接的配置,例如服务器地址、端口号、最大等待时间等;
  2. 配置完成后等待客户调用,客户调用特定方法,传入了参数。客户端调用选定的序列化例程对数据进行序列化,并且根据数据填充HTTP头信息;
  3. 客户端发起HTTP请求,将数据发送个服务器,等待服务器应答;
  4. 获取到服务器返回的数据后,对数据进行解析,返回给调用者。

fFig 3 FastRPC Client

整个请求的核心就是下面的几行代码,位于frpcserverproxy.cc中,首先将方法名和参数都序列化到本地的缓存,然后通过flush方法写到HTTP输出流:

// fastrpc\src\frpcserverproxy.cc...try {marshaller->packMethodCall(methodName);// marshall all passed values until null pointerwhile (const Value_t *value = va_arg(args, Value_t*))feeder.feedValue(*value);marshaller->flush();} catch (const ResponseError_t &e) {}...
// fastrpc\src\frpctreefeeder.cctemplate <typename Marshaller_t>
void feedValueImpl(Marshaller_t &marshaller, const Value_t &value) {switch(value.getType()) {case Int_t::TYPE:marshaller.packInt(Int(value).getValue());break;case Bool_t::TYPE:marshaller.packBool(Bool(value).getValue());break;case Null_t::TYPE:packNull(marshaller, value);break;...
// fastrpc\src\frpcbinmarshaller.ccvoid BinMarshaller_t::packInt(Int_t::value_type value) {if (protocolVersion.versionMajor > 2) {// pack via zigzag encoding.uint64_t zig = zigzagEncode(value);unsigned int numType = getNumberType(static_cast<Int_t::value_type>(zig));//pack typechar type = FRPC_DATA_TYPE(INT, numType);//pack number valueNumber_t number(zig);//write typewriter.write(&type, 1);writer.write(number.data, getNumberSize(numType));} else if (protocolVersion.versionMajor > 1) {...
// fastrpc\src\frpchttpclient.ccvoid HTTPClient_t::write(const char* data, unsigned int size) {contentLenght += size;if (size > (BUFFER_SIZE - queryStorage.back().size())) {if (useChunks) {sendRequest();queryStorage.back().append(data, size);} else {if (size > BUFFER_SIZE) {queryStorage.push_back(std::string(data, size));} else {queryStorage.back().append(data, size);}}} else {queryStorage.back().append(data, size);}
}
// fastrpc\src\frpchttpclient.ccvoid HTTPClient_t::sendRequest(bool last) {SocketCloser_t closer(httpIO.socket());std::string headerData;if (!headersSent) {HTTPHeader_t header;StreamHolder_t os;//create headeros.os << POST << ' ' << (url.isUnix() ? "/" : url.path) << ' '<< (useHTTP10 ? HTTP10 : HTTP11) << "\r\n";if (!useHTTP10) {os.os << HOST << ": ";if (!url.isUnix()) {os.os << url.host << ':' << url.port;}os.os << "\r\n";}...

4. 总结

说白了,RPC最终就是一个服务器和客户端。那么RPC和REST(Representational State Transfer,表示层状态转移)有什么区别呢?两者的区别就是在于对服务器请求的目的不同:REST需要服务器给出资源,例如一张图片一段数据,并且通过GET, PUT, UPDATE, DELETE等特定方法表述希望对这个资源进行的操作;而RPC客户端需要RPC服务器提供计算服务,你用我希望的任何方式对我提供的数据进行计算并告诉我结果。

公众号二维码

首发于个人微信公众号TensorBoy。微信扫描上方二维码或者微信搜索TensorBoy并关注,及时获取更多最新文章!
C++ | Python | 推理引擎 | AI框架源码,有一起玩耍的么?

5. References

[1] What differentiates a REST web service from a RPC-like one? 【stackoverflow】
[2] https://github.com/seznam/fastrpc


http://chatgpt.dhexx.cn/article/ZQ5GSDwp.shtml

相关文章

RPC原理详解

转自&#xff1a;http://www.cnblogs.com/metoy/p/4321311.html RPC 功能目标 RPC 的主要功能目标是让构建分布式计算&#xff08;应用&#xff09;更容易&#xff0c;在提供强大的远程调用能力时不损失本地调用的语义简洁性。 为实现该目标&#xff0c;RPC 框架需提供一种透…

RPC原理介绍

面向服务架构SOA 任何大型网站的发展都伴随着网站架构的演进。网站架构一般最初是单应用设计&#xff0c;然后逐渐经历面向对象设计和模块化设计的架构&#xff0c;最终发展到面向服务的服务化架构。在单应用设计架构体系当中&#xff0c;我们关注的是方法和实体&#xff1b;而…

RPC 原理与实现

文章目录 1. RPC 简介1.1 什么是RPCReference: LPC & IPC (本地过程调用) 1.2 为什么要用RPC1.2.1 系统架构的演进1.2.2 Web 服务的技术结构1.2.2 SOAP &#xff08; Simple Object Access Protocol&#xff09;1.2.2 REST&#xff08;Representational State Transfort&am…

RPC核心原理

了解RPC RPC全称Remote Procedure Call,即远程过程调用.其中远程需要跨机器,跨机器需要可靠的网络编程技术实现,无论是Java原生的网络编程模型还是Netty都会让代码中出现大量与业务无关的网络编程代码,RPC技术则是为了解决这个问题的.它帮助我们屏蔽网络编程的细节,实现调用远…

RPC原理(1)之深入RPC原理简介

一、RPC调用原理图 下面这张图是我们微服务一次Http调用请求图&#xff1a; 首先在请求的过程中我们知道是有三次握手&#xff0c;四次挥手的流程&#xff0c;具体流程如下&#xff1a; 1.浏览器请求服务器(订单服务)&#xff0c;请求建立连接&#xff0c;首先客户端向服务器…

RPC原理简述

RPC&#xff08;Remote Procedure Call&#xff09;&#xff1a;远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的思想。 RPC 是一种技术思想而非一种规范或协议&#xff0c;常见 RPC 技术和框架有&#xff1a; 应…

RPC核心原理详解

什么是RPC&#xff1f; RPC的全称是Remote Procedure Call&#xff0c;即远程过程调用。简单解读字面上的意思&#xff0c;远程肯定是指要跨机器而非本机&#xff0c;所以需要用到网络编程才能实现&#xff0c;但是不是只要通过网络通信访问到另一台机器的应用程序&#xff0c…

RPC原理

RPC就是远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的思想。 原理 一个完整的RPC主要包括三部分: 服务注册中心&#xff08;Registry&#xff09;&#xff0c;负责将本地服务发布成远程服务&#xff0c;管理远…

从零开始实现RPC框架 - RPC原理及实现

RPC概述 RPC(Remote Procedure Call)即远程过程调用&#xff0c;允许一台计算机调用另一台计算机上的程序得到结果&#xff0c;而代码中不需要做额外的编程&#xff0c;就像在本地调用一样。 现在互联网应用的量级越来越大&#xff0c;单台计算机的能力有限&#xff0c;需要借…

RPC介绍与原理

RPC介绍与原理 RPC介绍 RPC是什么 RPC&#xff08;Remote Procedure Call&#xff09;是一种进程间通信方式。简单地说就是能使应用像调用本地方法一样的调用远程的过程或服务&#xff0c;可以应用在分布式服务、分布式计算、远程服务调用等许多场景。说起 RPC 大家并不陌生…

RPC理论原理

目录 集群和分布式RPC通信原理 集群和分布式 集群&#xff1a;每一台服务器独立运行一个工程的所有模块。 分布式&#xff1a;一个工程拆分了很多模块&#xff0c;每一个模块独立部署运行在一个服务器主机上&#xff0c;所有服务器协同工作共同提供服务&#xff0c;每一台服务…

一文搞懂RPC原理

了解RPC&#xff1a; RPC&#xff08;Remote Procedure Call Protocol&#xff09;——远程过程调用协议&#xff1a; 一般用于实现部署在不同机器上的系统之间的方法调用&#xff0c;使得程序能够像访问本地资源一样&#xff0c;通过网络传输去访问远端系统资源。 描述&…

rpc简介及原理

1.RPC简介及原理介绍 RPC技术内部原理是通过两种技术的组合来实现的&#xff1a;本地方法调用 和 网络通信技术。 1.1 RPC简介 在上述本地过程调用的例子中&#xff0c;我们是在一台计算机上执行了计算机上的程序&#xff0c;完成调用。随着计算机技术的发展和需求场景的变化…

RPC原理解析

1.RPC原理解析 1.1 什么是RPC RPC(Remote Procedure Call Protocol)——远程过程调用协议&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在&#xff0c;如TCP/IP或UDP&#xff0c;为通信程序…

RPC实现原理

一、什么是RPC框架&#xff1f; RPC&#xff0c;全称为Remote Procedure Call&#xff0c;即远程过程调用&#xff0c;是一种计算机通信协议。 比如现在有两台机器&#xff1a;A机器和B机器&#xff0c;并且分别部署了应用A和应用B。假设此时位于A机器上的A应用想要调用位于B机…

什么是 RPC?RPC原理是什么?

什么是 RPC?RPC原理是什么? 什么是 RPC&#xff1f; RPC&#xff08;Remote Procedure Call&#xff09;—远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器…

【RK3399Pro学习笔记】三、Debian 9 安装 ROS (Thinker Edge R)

目录 配置源设置 Key安装初始化rosdep环境配置测试安装rosinstall卸载 平台&#xff1a;华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本&#xff1a;Tinker_Edge_R-Debian-Stretch-V1.0.4-20200615 参考资料&#xff1a; RK3399(Debian9 - stretch) 安装 ROS Lunar —— WB8…

VMware安装Debian9及开发环境配置

序 需要用到一个搭载armv7架构A7内核的Linux设备&#xff0c;装的是Debian系统&#xff0c;为便于兼容该设备故用VMware安装一个Debian9虚拟机&#xff0c;整理总结了网上一些信息以供参考。 目录 一、安装Debian91、WMware中的配置2、安装镜像 二、开发环境配置1、设置快捷键打…

debian 升级linux内核,Debian 9更新到最新的Linux内核

喜欢折腾的同学,会豪气如何升级 Debian Stretch 的内核到新版。遗憾的是现在能搜到的升级 Debian Linux 内核的文章多数是使用Ubuntu的deb安装包,其实这样装上去是有问题,常见的问题是,总会提示需要 apt --fix-broken install 。 这里简单记录一下,如何使用Debian官方源更…

debian 9 ssh root权限登录

debian 9默认的一样不能用root用户登录&#xff0c;还是需要设置&#xff0c;方法如下&#xff1a; 一&#xff0c;打开终端&#xff0c;用普通用户登录 输入&#xff1a;su - 输入密码&#xff0c;切换到root用户 二&#xff0c;设置root用户登录 nano /etc/ssh/sshd_conf…