RPC 快速入门
一、What
1)小故事
张三和李四都在同一个家公司负责商品交易的模块,两个人平时开发甚是紧密。
🙋🏻♂️ 张三:“李四,我这边一个商品下单了,但是付款数额不对,你帮我查下支付有没有问题”
🙋🏻 李四:“张三,支付这边检验价格的时候有点问题,实付金额和预付金额对不上”
往常,他们相邻而坐,有什么问题也是 张口就问 。但是随着业务的增长,他们的工作被细化到不同的子模块中,而 分布式系统 的概念也恰逢其时地变得流行起来。"拆分系统"的计划迫在眉睫。于是张三自然而然地分配到了订单模块,而李四到了交易模块。相应,两个人的工位也需要分开,这个时候他们意识到应该没法像从前那样即呼即应了 。
这个时候该如何解决沟通的问题?
李四人搬走了,但是 联系方式 还在,张三需要李四协助的时候可以通过 电话 的方式直呼李四,虽然说通过电话的这种方式略显间接,但仍然保留了解问题的能力,只是沟通的形式变了。
通过阅读这个故事,我们总结一下其中几个核心概念
- 张三李四可以直接交谈。(直接调用)
- 拆分模块(分布式系统)
- 联系方式(接口定位)
- 利用电话沟通(远程通信)
- 打电话的过程(过程调用)
而这几个概念也正是 RPC 的核心所在。
2)概要
RPC (Remote Procedure Call) 是一种用于实现远程通信和分布式计算的协议。它允许在不同的计算机或进程之间进行通信,使得这些计算机或进程能够像调用本地函数一样调用位于远程计算机或进程上的函数或方法。
RPC 协议的基本原理是客户端调用远程服务器上的函数,并将函数参数传递给服务器。 服务器执行相应的函数逻辑,并将结果返回给客户端。
从客户端的角度来看,RPC 调用就像是调用本地函数一样,而不需要关心远程函数的实现和通信细节。
简单来说:从本质上讲,它使一台机器上的程序能够调用另一台机器上的子程序,而不会意识到它是远程的。
3)HTTP
1、HTPP 与 RPC 的先后
RPC是一个较早的抽象,它的思想在1970年代早期就已经存在,而具体实现上的一个里程碑是在1980年代。它代表了一种通用概念:从一个计算机进程中调用另一个进程的函数或过程,无论这两个进程是否在同一台机器上。
HTTP首次出现在1991年。它是由蒂姆·伯纳斯-李在1990年至1991年期间开发的,作为万维网(World Wide Web,简称WWW)项目的一部分。
因此从时间线上看,RPC 是早于 HTTP 出现的。
2、既生 RPC 何生 HTTP
有了RPC,理论上可以通过各种协议进行方法调用,但HTTP为万维网提供了一个标准化的、广泛支持的方式来交换信息和服务,它不仅限于方法调用,还包括数据的获取、提交、更新和删除等。
比方说 A 公司开发了一套数据管理系统,在 A 公司内部可以使用 RPC 协议 进行方法调用获取数据,而这个时候 B 公司想要集成 A 公司的能力,这个时候通过方法调用的方式就不大合适,就需要利用万维网上更加标准的协议来进行通信,也就是 HTTP 协议。
主要区别
RPC 与 REST 最大的区别就在于 RPC 提供了更好的抽象,甚至将网络传输细节彻底隐藏了,而 REST 没有。具体来说,REST 至少要求用于提供 URL 以及请求参数,而 RPC 隐藏了与网络传输的相关实现细节。另一方面,RPC 可以基于任何网络通信协议,而 REST 通常基于 HTTP(或者 HTTPS)协议。
- 设计目标
- RPC 协议是一种用于实现远程过程调用的协议,它主要是让客户端能够像调用本地函数一样调用远程服务器上的函数。更侧重于方法的调用和参数传递,通常用于构建分布式系统、微服务架构等场景,提供了更直接的远程函数调用能力。
- HTTP 协议是一种通用的应用层协议。它提供了一套标准的请求和响应语义,支持网页浏览、资源访问、API 调用等场景。HTTP 具有广泛的应用范围,可以用于浏览器与服务器之间的通信,也可以用于不同系统之间的数据交换。
- 传输协议
- RPC 协议可以基于多种传输协议实现,如 TCP、UDP、HTTP 等,通过自定义的协议栈和编码方式来进行数据传输。
- HTTP 协议基于 TCP/IP,使用统一的格式规范,如请求行、请求头、请求体等,以及常见的编码方式如 JSON、XML、Form 表单等。
- 通信模型:
- RPC 协议是一种点对点的通信模型,客户端和服务器之间建立直接的连接,进行函数调用和返回结果。
- HTTP 协议是一种客户端-服务器模型,客户端发送请求,服务器接收请求并返回响应,每次请求都需要建立新的连接。
3、性能比较
HTTP 协议和 RPC 协议在性能方面有一些差异,这些差异主要由以下几个因素决定:
- 通信开销:
- HTTP 协议通常使用文本格式(如 JSON、XML)进行数据传输,相对较为冗长。每次请求和响应都会包含大量的头部信息,增加了数据传输的开销。
- RPC 协议通常使用二进制序列化格式(如 Protocol Buffers、Thrift),相对更为紧凑。它通常专注于方法调用和参数传递,减少了不必要的开销。
- 连接复用:
- HTTP 协议在默认情况下使用短连接,即每个请求都需要建立一个新的连接。这对于频繁的请求会增加连接建立和关闭的开销。
- RPC 协议通常支持长连接,在一个连接上可以进行多次的方法调用。这样可以减少连接的建立和关闭次数,提高性能。
- 序列化和反序列化:
- HTTP 协议使用通用的文本格式进行数据传输,需要进行文本到对象的序列化和反序列化操作。这些操作可能会消耗一定的时间和计算资源。
- RPC 协议通常使用二进制序列化格式,可以更高效地进行序列化和反序列化,减少了转换的开销。
相对来说,RPC 协议通常在性能方面比 HTTP 协议更优秀。由于 RPC 协议的设计目标更加专注于方法调用和参数传递,它通常采用更紧凑的数据格式、支持长连接等机制,以提供更高的性能和效率。但在实际应用中,具体的性能差异需要根据具体情况进行评估和测试。
二、How
1)核心概念
- 客户端(Client): 发起远程函数调用的一方。负责将本地的函数或方法调用转化为网络请求,并将网络响应转化回本地的函数或方法调用的结果。
- 客户端存根(Client Stub): 客户端存根将函数调用及其参数编码、序列化后通过网络发送请求。
- 网络模块(Network): 用于传输远程调用讯息的媒介,可以是TCP/IP、HTTP或其他网络协议。
- 服务端骨架(Server Skeleton): 与客户端存根对应,负责将接收到的请求解包、反序列化后调用实际的服务服务过程。并将结果重新包装发送回客户端。
- 服务端(Server): 提供远程过程实际执行的地方,即实现了具体逻辑的服务或应用程序。
2)通信流程
从上面中我们认识了 RPC 的五大概念,可以通过一张时序图将五大概念串行起来,如下:
具体流程:
- Client 客户端 通过调用本地服务的方式调用需要消费的服务
- Client Stub 存根 接收到调用请求后负责将方法,入参等信息序列化(组装)成能够进行网络传输的消息体
- Client Stub 存根 找到远程的服务地址,并且将消息通过网络发送给服务端
- Server Stub 服务端骨架 收到消息后进行解码(反序列化操作)
- Server Stub 服务端骨架 根据解码结果调用本地的服务进行相关处理
- Server 服务端 执行具体业务逻辑并将处理结果返回给 Server Stub 服务端骨架
- Server Stub 服务端骨架 将返回结果重新打包成消息(序列化)并通过网络发送至消费方
- Client Stub 存根 接收到消息,并进行解码(反序列化);
- Client Stub 存根 将解码后的结果返回给 Client 客户端
3)实现架构
当我们认识到 RPC 的通信架构了,进一步就可以考虑如何实现 RPC 框架了!
其中 Client 客户端 和 Server 服务端 是关键角色,一个负责消费,一个负责提供。在 Client 客户端 我们要实现无感知地侵入,达到客户端完全不会意识到 Server 服务端 的存在,就需要用上 Proxy 代理 能力。当代理拦截到客户端调用的方法后,还需要将数据序列化后进行发送,这个时候 Serializer 模块 就不可少,当序列完数据就得通过网络将数据进行传输,因此便需要 Network 模块,但是在传输之前,我们需要找到远程服务的地址,因此 Registry 注册中心 也少不了。
1、五大模块
通过简单梳理我们大概整理了 5 大模块:
- 客户端(Client): 客户端模块,发起远程函数调用请求。
- 序列化模块(Serializer): 序列化模块,负责数据的序列化和反序列化。
- 网络(Network): 网络模块,用于传输远程调用信息。
- 注册中心(Registry): 注册中心模块,负责服务的注册与发现。
- 服务端(Server): 提供远程过程实际执行的地方,即实现了具体逻辑的服务或应用程序。
架构图如下:
2、技术分析
聊完理论谈实践,为了实现以上各个模块之间的串行能力,我们需要用到的技术能力如下:
1)动态代理
生成 Client Stub 存根 和 Server Stub 服务端骨架 的时候需要用到 Java 的动态代理技术,可以使用JDK提供的原生的动态代理机制,也可以使用开源的CGLib代理, Javassist字节码生成技术。
在构建RPC框架时,生成 Client Stub 存根 和 Server Stub 服务端骨架 是实现远程方法调用不可或缺的一环。这一过程往往需要动态代理技术来实现,在Java平台上,我们有几种选择来达到这个目的。
- 使用JDK提供的原生的动态代理机制,它主要是通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来完成的,适用于需要代理接口而非类的场合。
- 使用开源的CGLib库。CGLib能够在运行时对类进行扩展,通过继承的方式生成新的子类,它不需要接口就能实现动态代理。
- Javassist 提供了一种更加直接操作字节码的方式,通过这种字节码技术,可以在不打破原有类结构的情况下,新增或者改变类的行为。
2)序列化
序列化是数据处理的关键环节,它使得复杂数据结构能够转换成字节序列,以便于存储或网络传输,这一过程亦称作编码。相对地,反序列化将这些字节序列重新构建成原始对象,即解码过程。在分布式系统与数据交换频繁的应用中,序列化的效率至关重要。
当评估并选择合适的序列化框架时,效率、灵活性和生态支持是几个关键的考量因素。当前市场上的一些高效开源序列化库,比如Kryo、FastJson和Protobuf,各自都有其优势。
- Kryo 是一个小巧且快速的序列化库,它被广泛应用于需要高速序列化操作的场景,尤其是在游戏和高性能计算中。
- FastJson 以其速度快和使用简单闻名,特别适用于Web服务和轻量级应用,它的优势在于处理JSON格式数据的高效性。
- Protobuf,由Google开发,是一个以效率和兼容性为主要目标的结构化数据序列化方法。相较于传统的XML,它更小、更快、更简单,且拥有良好的跨平台性。
3)网络通信
为了提高系统处理并发请求的能力,传统的同步阻塞IO(BIO)模型并不适宜,因为它在等待数据读写过程中会导致线程阻塞,从而降低了并发处理的效率。因此,采用非阻塞IO(NIO)是解决高并发场景下性能问题的恰当选择。NIO支持异步IO操作,允许线程在处理其它任务时并行地等待IO操作完成,这大大提升了资源的利用率和系统的吞吐量。
在构建高并发网络应用时,我们有多种框架可以选择。Netty和Apache MINA是两个流行的高性能网络应用框架,它们都利用了Java NIO的优势。Netty特别被广泛用于其简单的API和稳定的性能,而MINA同样提供了一个易于使用和扩展的异步IO框架。根据应用的具体需求和开发团队的熟悉度,我们可以选取最适合的框架来构建我们的网络服务,以确保在高并发场景下应用的最佳网络性能和响应速度。
4)注册中心
服务注册与发现是核心组件,它用于服务间的动态定位。市面上有多种成熟的服务注册中心方案,包括Redis、ZooKeeper、Consul等。其中,
选择合适的注册中心时,我们不仅需要考虑技术特性,比如数据一致性、可用性和可扩展性,还要考虑与现有系统环境的兼容性,以及未来的维护和支持情况。每种方案都有其特定优势和场景适用性,例如Redis在处理高速缓存和消息队列方面表现卓越,Consul提供更现代的服务网络功能,如健康检查和服务网格集成,ZooKeeper凭借其强一致性的特点,经常被选用来处理服务注册和发现的问题,同时有效解决分布式系统中避免单点故障及处理分布式部署的挑战
4)常见 RPC 框架
1、gRPC
- 开源RPC框架,由Google主导开发。
- 使用HTTP/2作为传输协议,以Protocol Buffers作为其接口定义语言。
- 支持多种编程语言,适用于构建跨语言的服务。
2、Apache Thrift
- 由Facebook开发并贡献给Apache的RPC框架。
- 支持多种编程语言,允许定义数据类型和服务接口在一个统一的接口描述语言(IDL)文件中。
- 框架生成服务端和客户端代码,供不同语言编写的程序使用。
3、Apache Dubbo
- 高性能的Java RPC框架。
- 用于构建大规模分布式系统,支持多种通信协议。
- 提供灵活的服务治理和动态配置功能。
三、End
在本篇文章中,我们探究了 RPC 的核心概念和基本原理,了解到其如何使得跨网络的服务调用变得透明而无缝。了解RPC不仅仅是关于掌握一个技术的使用,更是理解分布式系统设计中关于模块化、服务解耦、和伸缩性设计的深层次思想。
随着微服务架构的兴起,RPC也随之进化,适应了更复杂的网络模式和更严格的性能需求。无论你是一个初级开发者还是高级开发者,RPC都应该是你日常开发过程中绕不开的一个话题。未来的网络计算充满了无限可能,而RPC无疑将继续在其中扮演着重要的角色。感谢您的阅读!
相关文章:

RPC 快速入门
一、What 1)小故事 张三和李四都在同一个家公司负责商品交易的模块,两个人平时开发甚是紧密。 🙋🏻♂️ 张三:“李四,我这边一个商品下单了,但是付款数额不对,你帮我查下支付有没…...
使用Docker搭建Syslog-ng
Syslog-ng是一个可靠、多功能的日志管理系统,用于收集日志并将其转发到指定的日志分析工具。 使用Docker CLI方式搭建 步骤 1: 拉取Syslog-ng镜像 首先,需要从Docker Hub拉取Syslog-ng的官方镜像。 docker pull balabit/syslog-ng:latest步骤 2: 启动…...

使能 Linux 内核自带的 FlexCAN 驱动
一. 简介 前面一篇文章学习了 ALPHA开发板修改CAN的设备树节点信息,并加载测试过设备树文件,文件如下: ALPHA开发板修改CAN的设备树节点信息-CSDN博客 本文是学习使能 IMX6ULL的 CAN驱动,也就是通过内核配置来实现。 二. 使能…...

通过dbeaver链接dm8数据库
一、环境说明 windows 11 vmware 17 ubuntu 22 tt:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammytt:~$ docker info Client:Version: 24.0.5Context: d…...

Stable diffusion(四)
训练自己的Lora 【DataSet】【Lora trainer】【SD Lora trainer】 前置的知识 batch size:模型一次性处理几张图片。一次性多处理图片,模型能够综合捕捉多张图片的特征,最终的成品效果可能会好。但是处理多个batch size也意味着更大的显存…...

oracle 19c RAC补丁升级
1.停止集群件备份家目录 ----两节点分别操作 cd /u01/app/19.3.0/grid/bin/ crsctl stop crstar -zcvf /u01/app.tar.gz /u01/app/u01/app/19.0.0/grid/bin/crsctl start crs2.两节点 GI、DB OPatch 替换(都得执行) ----# 表示 root 用户,$…...
计算机视觉研究方向
计算机视觉是一个广泛且快速发展的领域,涵盖了多种研究方向和技术。主要的研究方向包括图像处理、目标检测与识别、图像生成、三维视觉、行为识别、深度学习与计算机视觉、多媒体分析、视频理解、风格化、全向视觉传感器等。这些研究方向和技术不断进步,…...
数据分析-Pandas分类数据的比较如何避坑
数据分析-Pandas分类数据的比较如何避坑 数据分析和处理中,难免会遇到各种数据,那么数据呈现怎样的规律呢?不管金融数据,风控数据,营销数据等等,莫不如此。如何通过图示展示数据的规律? 数据表…...

P - Beat
题目分析 1.看数据范围,大概知道dfs能做 2.自0问题开始查找,确保之后每次查找到的问题的困难度均大于上一次 3.遍历所有情况再记录cnt即可 代码 #include <iostream> #include <algorithm> #include <cstdio> #include <cstring&…...

机器学习——GBDT算法
机器学习——GBDT算法 在机器学习领域,梯度提升决策树(Gradient Boosting Decision Trees,简称GBDT)是一种十分强大且常用的集成学习算法。它通过迭代地训练决策树来不断提升模型性能,是一种基于弱学习器的提升算法。…...

阿里二面:谈谈ThreadLocal的内存泄漏问题?问麻了。。。。
引言 ThreadLocal在Java多线程编程中扮演着重要的角色,它提供了一种线程局部存储机制,允许每个线程拥有独立的变量副本,从而有效地避免了线程间的数据共享冲突。ThreadLocal的主要用途在于,当需要为每个线程维护一个独立的上下文…...
IOS面试题编程机制 46-50
46. 阐述 Method Swizzle(黑魔法),什么情况下会使用?1). 在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有更加灵活的方法 Method Swizzle。 2). Method Swizzle 指的是改变一个已存在的选择器对应的实现…...

web表单标签与练习(3.18)
一、表单域 表单域是一个包含表单元素的区域。 在HTML标签中,< form >标签用于定义表单域,以实现用户信息和传递。 < form >会把它范围内的表单元素信息提交给服务器。 表单属性 action url地址 用于指定接收并处理表单数据的服务器程序的…...

【协议-HTTP】
HTTP协议 HTTP协议(超文本传输协议HyperText Transfer Protocol),它是基于TCP协议的应用层传输协议。http协议定义web客户端如何才能够web服务器请求web页面,以及服务器如何把web页面传送给客户端。 HTTP 是一种无状态 (stateless) 协议, HTTP协议本身…...
VUE3v-text、v-html、:style的理解
在Vue 3中,v-text、v-html和:style是三个常用的指令,它们各自具有不同的功能和用途。 v-text: v-text用于操作元素中的纯文本内容。它接受一个表达式,并将该表达式的值设置为元素的文本内容。如果元素原本有文本内容,…...
Dataset之UCI_autos_cars:UCI_autos_imports-85(汽车进口数据集)的简介、安装、案例应用之详细攻略
Dataset之UCI_autos_cars:UCI_autos_imports-85(汽车进口数据集)的简介、安装、案例应用之详细攻略 目录 UCI_autos_imports-85的简介 UCI_autos_imports-85的安装 UCI_autos_imports-85的案例应用 1、训练一个简单的线性回归模型来预测汽车的价格 UCI_autos_i…...

结构体类型详细讲解(附带枚举,联合)
前言: 如果你还对结构体不是很了解,那么本篇文章将会从 为什么存在结构体,结构体的优点,结构体的定义,结构体的使用与结构体的大小依次介绍,同样会附带枚举与联合体 目录 为什么存在结构体: 结构…...
编程生活day1--个位数统计、考试座位号、A-B、计算阶乘和
个位数统计 题目描述: 定一个 k 位整数 Ndk−110k−1⋯d1101d0 (0≤di≤9, i0,⋯,k−1, dk−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N100311,则有 2 个 0,3 个 1,和 …...

mysql体系结构及主要文件
目录 1.mysql体系结构 2.数据库与数据库实例 3.物理存储结构编辑 4.mysql主要文件 4.1数据库配置文件 4.2错误日志 4.3表结构定义文件 4.4慢查询日志 4.4.1慢查询相关参数 4.4.2慢查询参数默认值 4.4.3my.cnf中设置慢查询参数 4.4.4slow_query_log参数 4.4.…...

PwnLab靶场PHP伪协议OSCP推荐代码审计命令劫持命令注入
下载链接:PwnLab: init ~ VulnHub 安装: 打开vxbox直接选择导入虚拟电脑即可 正文: 先用nmap扫描靶机ip nmap -sn 192.168.1.1/24 获取到靶机ip后,对靶机的端口进行扫描,并把结果输出到PwnLab文件夹下,命名…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...