RPC框架的核心是什么
文章目录
- 什么是 RPC
- 封装的艺术(如何隐藏底层逻辑)
- 协议的实现
- 序列化和反序列化(编解码)
- 总结
什么是 RPC
首先思考这样一个问题,假设你不知道任何框架,现在有两台机器,每台机器上有一个服务,让你在其中的一个服务中调用另一个服务中的接口,怎么样才能做到呢?
RPC 全称为远程过程调用(Remote Procedure Call Protocol),通俗点来说,就是从一台机器通过网络调用到另一台机器的某个方法。
那这样说来的话,通过 Socket 调用另一台机器的 Sokcet 服务也是RPC,通过一些 HTTP 请求工具包调用一个远程 HTTP 接口也是 RPC 了。
最开始的 RPC 定义还有可能是这样的,但是这种方式太底层、太繁琐了。
现在的 RPC 除了要有明显的网络通信特征外,还要具备下面几个特点:
- 良好的封装:让我们感觉调用远程接口就好像是调用本地方法一样方便,封装底层网络通信的细节,让我们更专注于业务逻辑。
- 良好的协议设计:数据在调用方和提供方传输,数据组织要遵循约定好的协议格式,比如 HTTP 协议、TCP 协议这种。
- 高效的序列化和反序列化:远程调用,所以很大一部分开销来自于数据传输,所以原则上数据量越小越好,这就依赖于序列化的算法了。
封装的艺术(如何隐藏底层逻辑)
如果每次调用提供方提供的方法时都像下面这样繁琐,指明 URL、自己构造 JSON 序列化字符串等等,会不会不太方便。
public static final MediaType JSON= MediaType.get("application/json; charset=utf-8");OkHttpClient client = new OkHttpClient();String post(String url, String json) throws IOException {RequestBody body = RequestBody.create(json, JSON);Request request = new Request.Builder().url(url).post(body).build();try (Response response = client.newCall(request).execute()) {return response.body().string();}
}
而像 Dubbo 这样调用,如果没有接触过 RPC 的人,刚看到这段代码会感觉到好像就是在调用本地的一个方法。隐藏了很多的细节。
@DubboReference
private DemoService demoService;String result = demoService.sayHello("world");
System.out.println("Receive result ======> " + result);
这就是现代 RPC 里一个很重要的特性,就是封装,尽量隐藏网络上的细节,让使用者感觉就是在调用本地的方法。

那在一般的 RPC 框架中,例如 Dubbo、GRPC等,是如何进行封装的呢。
我们看上面的图,其中调用方和服务提供方都有一个部分叫做存根(Stub),就是靠的它。听上去感觉这词不太容易理解啊,啥叫存根呢,其实说简单点儿就是一个代理方案。
举个例子,当我们调用本地的一个服务类的某个方法时,实际上这个服务类已经是一个代理类了,调用这个类的某个方法,实际上代理方法中可以加入很多额外的逻辑,比如构造 HTTP 请求、构造TCP 请求等等,最终穿过网络调用到真正的服务提供方的同名方法。
说到 Java 中的代理技术,相信大家都不陌生,有动态代理、静态代理,不了解的同学可以参考 Spring AOP 和 动态代理技术 这篇文章。
协议的实现
这里说的协议就是网络通信协议。远程过程调用嘛,那必须得通过网络传输才行,而通过网络传输那就得有遵行规定的协议。
这个协议是用来规范传输的数据的,所以它是一个应用层协议,比如 HTTP ,而不是传输层的协议,比如 TCP 、UDP 。
比如 GRPC 框架中用的协议是 HTTP2,Dubbo中可以选择多种协议,比如Hession、HTTP等。
下图是 HTTP 1.0 协议的格式,包括首部和请求内容,首部可以指定请求方式、URI、版本、内容类型和长度等,内容部分就是真正要传输的数据, 如果是一个 RPC 调用的话,那就是调用方法的参数和一些额外的信息(比如调用的方法名、类名等),首部和内容由一个空行分隔。
接收端可以根据空行了解哪些是头部,哪些是内容。
可以通过首部的内容长度字段来进行分配内存或其他操作。

其他的协议都有自己的格式,我们也可以自定义一个协议。如下是一个简单的协议格式:
通过魔术位可以直接判断是不是本协议数据,如果是的话,再进行处理。
通过整体长度和首部长度可以确定数据内容的长度,用来解析首部和数据。
通过序列化方式字段可以确定数据序列化采用的什么方式,用来实现反序列化。
| 0-8bit | 9-24bit | 25-32bit | 33-40bit |
|---|---|---|---|
| 不定长标志位(魔术位) | 整体长度 | 首部长度 | 序列化方式 |
一个 RPC 框架使用哪种协议是有权衡取舍的,如果考虑通用性那就可能使用 HTTP或者 HTTP2这种协议,比如 GRPC ,这样一来,可以在各种语言框架中通用,但是性能就稍微差一点了。
而如果从性能方面考虑呢,那就要牺牲掉一部分通用性了,比如Hession、Dubbo2协议,只有框架开发者提供了对应语言的版本,才能在相应的语言中使用。
序列化和反序列化(编解码)
上面说的协议主要指的是数据通信协议,而序列化和反序列化其实也要遵循一定的协议。
说到序列化和反序列化,其实我们并不陌生。在Java开发中,经常会遇到。最常用的就是把 Java Bean 序列化为 JSON,将 JSON 反序列化为 Java Bean。
JSON 就是最常见的一种序列化和发序列化协议,其他的序列化方式还有 XML、GRPC 中用到的 Protocol Buffers。 Hessian 也有它自己的序列化算法。
为什么要有序列化呢,数据要想在网络中传输,那必须是二进制的形式。在远程调用里,我们像调用本地方法那样调用,使用的参数都是和当前项目语言一致的参数类型,比如Java中的 String、List、Map等等,那要把这些类型转换成二进制,靠的就是序列化算法。
JSON 和 XML 这种文本序列化方式比较简单,使用场景非常广泛,通用性强,但是序列化后产生的二进制体积也比较大,这样在传输的时候就会比较耗时、占用带宽。
而像 Protocol Buffers 这种序列化方式,它使用结构化的消息定义语言(IDL)来定义数据结构和服务接口,支持多种编程语言,而且序列化后的二进制也会最大程度的压缩,少占用带宽,有很高的传输效率。
总结
下图是整个 RPC 调用过程的简化版。

序列化和反序列化功能会在代理中进行,在很多框架中也称这部分为编解码。
封装的网络请求既有可能是 HTTP 请求,也有可能是 Sockets 请求,比如有很多 RPC 功能都使用 Netty 作为通讯层。
除了主要的功能外,一个成熟的 RPC 框架还有考虑诸多其他因素,比如性能、安全性、兼容性等等。
相关文章:
RPC框架的核心是什么
文章目录 什么是 RPC封装的艺术(如何隐藏底层逻辑)协议的实现序列化和反序列化(编解码)总结 什么是 RPC 首先思考这样一个问题,假设你不知道任何框架,现在有两台机器,每台机器上有一个服务&…...
直播、AI赋能,美团披着荆棘前行
随着互联网流量红利逐渐消退,阿里、抖音、腾讯、拼多多、快手、小红书等各赛道玩家,为了寻求新的增量,纷纷“卷”向本地生活,开始入侵美团的腹地。然而,哪怕巨头环伺,美团仍然展现出了其独特的竞争力&#…...
提升代码逻辑的感觉——python循环语句
提升代码逻辑的感觉——python循环语句 简介 循环是编程中的一个非常重要的概念,它用于处理重复性任何和迭代草错,通过循环我们能优化并简化代码,提高代码的可维护性,在Python中循环是一种控制结构,允许我们重复执行…...
【ARM Coresight 系列文章 20 -- linux perf 与 ARM coresight】
文章目录 1.1 Perf Introduction1.1.1 Perf 架构图1.1.2 Perf Tools 介绍1.1.3 Perf 命令介绍1.2 Events1.2.1 Perf 与 PMU 的关系1.2.2 Hardware events1.2.1.1 linux perf 事件分类1.2.2 Software Events1.2.3 Tracepoint Events1.3 Perf 工具使用1.4 用户态开发1.4.1 用户态…...
微服务之Nacos
1 版本说明 官网地址: https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 1.1 2021.x 分支 适配 SpringBoot 2.4, Spring Cloud 2021.x 版本及以上的Spring Cloud Alibaba 版本如下表(最新版本用*标记&am…...
jvm 新生代的区域划分
虚拟机将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次分配内存只使用 Eden 和其中一块 Survivor。发生垃圾收集时,将 Eden 和 Survivor 中仍然存活的对象一次性复制到另外一块 Survivor 空间上,然后直接清理掉 Eden 和已用过…...
【C++】对于string的补充(成员函数c_str()、大小写转换、字符串和实数之间的相互转换)
前言 本篇文章记录的是一些关于string的补充说明 string与const char*之间的相互转换 const char* 转换成string 在C中存在着从const char到string的隐式类型转换,换句话说,如果一个函数的参数类型是string类,直接传入const char类型的参…...
华为OD机试真题【羊狼农夫过河】
1、题目描述 【羊、狼、农夫过河】 羊、狼、农夫都在岸边,当羊的数量小于狼的数量时,狼会攻击羊,农夫则会损失羊。农夫有一艘容量固定的船,能够承载固定数量的动物。要求求出不损失羊情况下将全部羊和狼运到对岸需要的最小次数。…...
【线性代数-3Blue1Brown】- 5 三维空间的线性变换
飞书原文档:Docs...
Maven入门教程(二):idea/Eclipse使用Maven
Maven入门教程(一):安装Maven环境 4.开发工具配置 4.1 idea配置 idea有多个版本,配置是一样的,只是配置页面的入口不一样 旧版idea 新版idea 4.2 Eclipse配置 打开Eclipse,菜单中选择:Window -> Preference ->…...
【MySQL】MySQL里的用户账户和角色是什么?如何管理?
用户(user)验证和授权创建用户账户连接服务器查看用户账户设置 角色(role)创建角色 操作用户帐户和角色重命名删除 感谢 💖 用户(user) 在MySQL中,用户是数据库访问的主要实体。每个…...
vbs病毒
vbs脚本:VBS脚本病毒原理分析和防范 疯狂代码 http://CrazyCoder.cn/ Sh t t p : / C r a z y C o d e r . c n / S e c u r i t y / Ar t i c l e 7 2 0 0 8 . h t m l 网络流行让我们世界变得更加美好但它也有让人不愉快时候当您收到封主题为1LoveYou” 邮件用兴奋 得几乎快发…...
用Java实现Huffman编码
文章目录 前言一、实现思路二、准备Huffman结点三、主要实现 前言 在使用http1.1协议传输数据的时候,会有一些固定的字段,比如cookie、编码方式、接收的数据类型,另外会有一些大量重复的字段造成请求报文过于冗长,为了解决这个问…...
day-04 基于UDP的服务器端/客户端
一.理解UDP (一)UDP套接字的特点 UDP套接字具有以下特点: 无连接性:UDP是一种无连接的协议,这意味着在发送数据之前,不需要在发送方和接收方之间建立连接。每个UDP数据包都是独立的,它们可以独…...
FFmpeg rtp rtp_mpegts的区别
rtp 在FFmpeg中,rtpenc是一个用于将音视频数据封装成RTP(Real-time Transport Protocol)数据包并发送到网络上的编码器。RTP是一种用于实时传输音视频数据的协议,常用于视频会议、流媒体等场景。 rtpenc可以将音视频数据封装成R…...
【链表OJ】相交链表 环形链表1
前言: 💥🎈个人主页:Dream_Chaser~ 🎈💥 ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 一.leetcode 160. 相交链表 1.问题描述: 2.解题思路: 二.leetcode 141.环形链表 …...
DevOps之自动化测试
什么是自动化测试? 明确一下自动化测试不是什么。自动化测试不是指自动化生成测试代码,而是自动化地执行由开发人员或测试人员编写的测试代码。正如下面这句谚语:“绝不要手工去做任何可以被自动化处理的事情。——Curt Hibbs” 之前是由人…...
Java 程序打印 OpenCV 的版本
我们可以使用 Java 程序来使用 OpenCV。 OpenCV 的使用需要动态库的加载才可以。 加载动态库 到 OpenCV 的官方网站上下载最新的发布版本。 Windows 下载的是一个可执行文件,没关系,这个可执行文件是一个自解压程序。 当你运行以后会提示你进行解压。…...
ChatGPT⼊门到精通(2):ChatGPT 能为我们做什么
⼀、雇佣免费的⼲活⼩弟 有了ChatGPT后,就好⽐你有了好⼏个帮你免费打⼯的「⼩弟」,他们可以帮你做很多 ⼯作。我简单总结⼀些我⽬前使⽤过的⽐较好的基于ChatGPT的服务和应⽤。 1、总结、分析 当我们在阅读⼀些⽂章和新闻的时候,有的⽂章写…...
线程和进程的区别是什么?
线程(Thread)和进程(Process)是操作系统中两个重要的概念,用于管理程序的执行。它们有以下区别: 定义:进程:进程是程序的一个执行实例,它包含了程序的代码、数据以及执行上下文。进程是操作系统分配资源和调度的基本单位。线程:线程是进程的子执行单元,一个进程可以…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
