RPC架构基本结构和核心技术

当你在构建一个分布式系统时,势必需要考虑的一个问题是:如何实现服务与服务之间高效调用?当然,你可以使用Dubbo或Spring Cloud等分布式服务框架来完成这个目标,这些框架帮助我们封装了技术实现的复杂性。那么,假如没有这些框架,而需要自己来实现远程调用,你应该怎么做的?这就需要引入今天讨论的话题:RPC架构。

RPC架构的基本结构

RPC的英文全称为Remote Procedure Call,也就是远程过程调用。我们通常把发生交互关系的两个服务分别称为服务的提供者(Provider)和消费者(Consumer)。简单来说,RPC就是用来实现服务的消费者向提供者发起远程调用的过程,这是RPC最简单的一种表现形式。


接下来,如果我们把上图做一些展开。如果想要实现服务提供者和消费者之间的有效交互,那么两者之间就需要确立与网络通信相关的网络协议以及通信通道。同时,服务的提供者需要把自己的服务调用入口暴露出来,并时刻准备接收来自消费者的请求。这样,RPC架构就演变成这个样子。


在上图中,我们把通信通道和网络协议分别命名为RpcChannel和RpcProtocol,而把提供者接收请求的组件称为RpcAcceptor,把消费者发起请求的组件称为RpcConnector。

然后,对于服务提供者和消费者而言,为了双方能够正常识别所发送的请求和所接收到的响应结果,需要定义统一的契约。我们把这种契约称为远程API,以与本地API进行区别。基于同一套远程API的定义,RPC架构就具备了根据业务来定义通信契约的能力。

类似的,为了我们更好的区分RPC架构中的角色,我们把真正提供业务服务的组件称为RpcServer,而把发起真实客户端请求的组件称为RpcClient。这样,RpcServer负责实现远程API,而RpcClient负责调用远程API。


当然,对于远程API而言,服务提供者和消费者的处理方式显然是不一样的。提供者需要根据消费者的请求来调用RpcServer的具体实现并返回结果,这部分的工作由RpcInvoker来执行,而消费者通过RpcCaller组件对请求进行编码之后发送到服务方并等待结果。

最后,为了降低开发人员的开发难度,让远程调用的执行过程看上去就先在执行本地方法一样,在主流的RPC实现方法中通常都会在客户端添加代理机制的实现组件RpcProxy,从而提供远程服务本地化访问的入口。另一方面,在服务器端,为了更好地控制业务方法执行过程,通常也会引入具备线程管理、超时控制等机制的RpcProcessor组件。


这样,我们对整个RPC架构的演进过程做了详细的描述。可以看到RPC架构有左右对称的两大部分构成,分别代表了一个远程过程调用的客户端和服务器端组件。客户端组件与职责包括:

  1. RpcClient,负责导入(import)由RpcProxy提供的远程接口的代理实现
  2. RpcProxy,远程接口的代理实现,提供远程服务本地化访问的入口
  3. RpcCaller,负责编码和发送调用请求到服务方并等待结果
  4. RpcConnector,负责维持客户端和服务端连接通道和发送数据到服务端

服务端组件与职责包括:

  1. RpcServer,负责导出(export)远程接口
  2. RpcInvoker,负责调用服务端接口的具体实现并返回结果
  3. RpcAcceptor,负责接收客户方请求并返回请求结果
  4. RpcProcessor,负责在服务方控制调用过程,包括管理调用线程池、超时时间等

而客户端和服务器端所共有的组件包括:

  1. RpcProtocol,负责网络传输协议的编码和解码
  2. RpcChannel,网络数据传输通道

这样,我们对一个典型RPC架构中的基本结构和组件已经都了解了,接下来我们再来重点分析想要实现这个架构中所应该具备的技术体系。

RPC架构的技术体系

从RPC架构的基本结构和组件出发,我们可以进一步梳理想要实现RPC架构的技术体系,包括网络通信、序列化、传输协议和远程调用。

网络通信

首当其中的无疑是网络通信。网络通信涉及面很广,RPC架构中的网络通信关注于网络连接、IO模型和可靠性设计。

基于TCP协议的网络连接有两种基本方式,也就是通常所说的长连接和短连接。长连接和短连接的产生在于客户端和服务器端采取的关闭策略,具体的应用场景采用具体的策略,没有十全十美的选择,只有合适的选择。在RPC框架实现过程中,考虑到性能和服务治理等因素,通常使用长连接进行通信,典型的实现框架就是Dubbo。

关于IO模型,最简单、最基础的就是阻塞式IO(Blocking IO,BIO),BIO要求客户端请求数与服务端线程数一一对应,显然服务端可以创建的线程数会成为系统的瓶颈。因此,在RPC架构中,我们通常都会使用非阻塞IO(Non-blocking IO,NIO)技术来提供性能。

由于存在网络闪断、超时等网络状态相关的不稳定性以及业务系统本身的故障,网络之间的通信必须在发生上述问题时能够快速感知并修复。常见的网络通信保障手段包括链路有效性检测以及断线之后的重连处理等

序列化

想要在网络上传输数据,就需要用到数据序列化技术。序列化的方式有很多,常见的有文本和二进制两大类。XML和JSON是文本类序列化方式的代表,而二进制实现的方案包括Google的Protocol Buffer和Facebook的Thrift等。

性能可能是我们在序列化工具选择过程中最看重的一个指标。性能指标主要包括序列化之后码流大小、序列化/反序列化速度和CPU/内存资源占用。下表中我们列举了目前主流的一些序列化技术:

序列化时间

反序列化时间

大小

压缩后大小

Java 

8654

43787

889

541

hessian

6725

10460

501

313

protocol buffer

2964

1745

239

149

thrift

3177

1949

349

197

json-lib

45788

149741

485

263

jackson

3052

4161

503

271

fastjson

2595

1472

468

251

可以看到在序列化和反序列化时间维度上Alibaba的fastjson具有一定优势,而从空间维度上看,相较其他技术我们可以优先选择Protocol Buffer。

传输协议

在ISO/OSI的7层网络模型中,RPC架构的设计和实现通常会涉及传输层及以上各个层次的相关协议,通常所说的TCP协议就属于传输层,而HTTP协议则位于应用层。传输协议的消息包括消息头和消息体两部分,消息体表示需要传输的业务数据,而消息头用于进行传输控制。图


图7

可以看到每个层次都从上层取得数据,加上消息头信息形成新的数据单元,并将新的数据单元传递给下一层次。

我们可以使用TCP协议和HTTP协议等公共协议作为基本的传输协议构建RPC架构,也可以使用基于HTTP协议的Web Service和RESTful风格设计更加强大和友好的数据传输方式。但大部分RPC框架内部往往使用私有协议进行通信,这样做的主要目的是对共有协议进行精简,从而提升性能。另一方面,出于扩展性的考虑,具备高度定制化的私有协议也比公共协议更加容易实现扩展。这方面典型的示例还是Dubbo框架,它提供了完全自定义的Dubbo协议。

远程调用

RPC本质也是一种服务调用,而服务调用存在两种基本方式,即单向(One Way)模式和请求应答(Request-Response)模式,前者体现为异步操作,而后者一般执行同步操作。

同步调用会造成业务线程阻塞,但开发和管理相对简单。同步调用时序图如下所示,我们可以看到服务线程发送请求到IO线程之后就一直处于等待阶段,直到IO线程完成与网络的读写操作之后被主动唤醒。


使用异步调用的目的在于获取高性能。在实现异步调用过程中,我们通常都会使用到Java中所提供的了Future机制。Future调用可以进一步细分成两种模式,Future-Get模式和Future-Listener模式。Future-Get模式参考下图:


可以看到这种模式下通过主动get结果的方式获取Future结果,而这个get过程是串行的,会造成执行get方法的线程形成阻塞。而Future-Listener模式则不同,在Future-Listener模式中需要创建Listener,当Future结果生成时会唤醒注册到该Future上的Listener对象,从而形成异步回调机制。

除了同步和异步调用之外,还存在并行(Parallel)调用和泛化(Generic)调用等调用方法,虽然也有其特定的应用场景,但对于RPC架构而言并不是主流的调用方式,这里不做具体展开。

可以说,RPC是分布式系统中一项基础设施类的技术体系,但凡涉及到服务与服务之间的交互就需要使用到RPC架构。当你在使用一个分布式框架时,可以尝试使用今天介绍的RPC架构的基本结构和技术体系进行分析,从而加深对这项技术体系的理解。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读】-- 研究时间序列可视化,提升用户体验

Investigating Time Series Visualisations to Improve the User Experience 摘要1 引言2 相关工作互动技巧视觉编码坐标系 3 用户研究时间序列可视化互动技巧任务实验设计 4 结果交互技术的效果视觉编码的影响坐标系的影响 5 讨论交互技术的效果视觉编码的影响坐标系的影响 6 …

[JS]正则表达式

介绍 正则表达式是定义匹配字符串的规则, 在JS中, 正则表达式也是对象, 通常用于查找或替换符合规则的文本 许多语言都支持正则表达式, 在前端中常见的场景就是表单验证和敏感词替换 语法 正则字面量 / / const str 好好学习,天天向上 // 1.定义规则: const reg /好///…

17964 水桶打水

这是一个优先队列(堆)和贪心算法的问题。我们可以使用C来解决这个问题。 首先,我们需要创建一个优先队列来存储每个水龙头的结束时间。然后,我们将所有人的打水时间从小到大排序。接着,我们将每个人分配给最早结束的水…

深入解析Flowable:工作流与业务流程管理引擎

深入解析Flowable:工作流与业务流程管理引擎 引言 在数字化时代,企业对流程自动化的需求日益增长。有效的工作流和业务流程管理系统可以帮助组织提高生产力、优化资源分配以及增强决策支持。Flowable是一款开源的工作流和业务流程管理(BPM&a…

MeterSphere v3.0全新启航,让软件测试工作更简单、更高效

2024年7月1日,MeterSphere v3.0版本正式发布。MeterSphere v3.0是新一代的测试管理和接口测试工具,致力于让软件测试工作更简单、更高效,不再成为持续交付的瓶颈。 在团队协作方面,针对目前企业软件测试团队所面临的测试工具不统…

springboot项目requestId设置、统一responsebody封装以及切面

利用filter设置requestId import cn.hutool.core.lang.UUID; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.s…

绿联NAS进入SSH的方法

1. 进入【设备管理】,在调试功能中,开启远程调试功能,发送手机验证码,你将得到一个3天有效期的验证码,就是ssh登录密码。 2. 使用终端工具或ssh命令直接登录SSH。 端口是922,账号是:root&#…

界面组件DevExpress WPF v24.1 - 增强的可访问性 UI自动化

DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 DevExpress WPF控件日…

全网最详细的 gin框架请求数据绑定Bind 源码解析 -- 帮助你全面了解gin框架的请求数据绑定原理和方法

在gin框架中,我们可以将多种请求数据(json, form,uri,header等)直接绑定到我们定义的结构体,底层是通过反射方式获取我们定义在结构体上面的tag来实现请求数据到我们的结构体数据的绑定的。 在gin的底层有2大体系的数据…

华为HCIP Datacom H12-821 卷19

1.多选题 如图所示,RTA 的 GE0/0/0、GE0/0/1 接口分别连接部门 1 和 2,其网段分别为 10.1.2.0/24、 10.1.3.0/24 网段,为限制部门 1 和 2 之间的相互访问,在 RTA 上部署 traffic-filter,以下哪些部署方式是正 确? A、配置 ACL3000 拒绝源为 10.1.2.0/24 目的为 10.1.3.0…

matlab仿真 通信信号和系统分析(上)

(内容源自详解MATLAB/SIMULINK 通信系统建模与仿真 刘学勇编著第三章内容,有兴趣的读者请阅读原书) 一、求离散信号卷积和 主要还是使用卷积函数conv,值得注意的是,得到的卷积和长度结果为81&#xff0…

【正点原子K210连载】第十四章 按键输入实验 摘自【正点原子】DNK210使用指南-CanMV版指南

1)实验平台:正点原子ATK-DNK210开发板 2)平台购买地址https://detail.tmall.com/item.htm?id731866264428 3)全套实验源码手册视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban 第十四章 按键输入实…

短信验证码API的防护策略?怎么优化更新?

短信验证码API的定制化服务怎么样?如何选择API服务? 短信验证码API成为保护用户账户和数据的重要工具,对短信验证码API的防护也显得尤为重要。AoKSend将探讨短信验证码API的防护策略,帮助企业和开发者确保系统的安全性和可靠性。…

FatFs(文件系统)

1官网 FatFs - 通用 FAT 文件系统模块 (elm-chan.org) FatFs 是用于小型嵌入式系统的通用 FAT/exFAT 文件系统模块。FatFs 模块是按照 ANSI C (C89) 编写的,并且与磁盘 I/O 层完全分离。因此,它独立于平台。它可以集成到资源有限…

2024 vue3入门教程:01vscode终端命令创建第一个vue项目

参考vue官网手册:https://cn.vuejs.org/guide/quick-start.html 一、找个盘符,新建文件夹存储以后得vue项目 我的是e盘下创建了vueproject 二、使用vscode打开存储vue项目的文件夹 因为我生成过项目,所以有文件,你们初次是没有…

【第五节】C/C++数据结构之图

目录 一、图的基本概念 1.1 图的定义 1.2 图的其他术语概念 二、图的存储结构 2.1 邻接矩阵 2.2 邻接表 三、图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四、最小生成树 4.1 最小生成树获取策略 4.2 Kruskal算法 4.3 Prim算法 五、最短路径问题 5.1 Dijkstra算…

WPF----自定义滚动条ScrollViewer

滚动条是项目当中经常用到的一个控件&#xff0c;大部分对外项目都有外观的需求&#xff0c;因此需要自定义&#xff0c;文中主要是针对一段动态的状态数据进行展示&#xff0c;并保证数据始终在最新一条&#xff0c;就是需要滚动条滚动到底部。 1&#xff0c;xaml中引入 <…

【大模型系列】Language-Vision Transformer(LaVIT, ICLR2024)

Title&#xff1a;Unified Language-Vision Pretraining in LLM with Dynamic Discrete Visual TokenizationPaper&#xff1a;https://arxiv.org/abs/2309.04669Github&#xff1a;https://github.com/jy0205/LaVITAuthor&#xff1a;Yang Jin&#xff0c; 北大&#xff0c;快…

Android Native 客户端属性配置系统使用说明

Android Native 客户端属性配置系统使用说明 背景和问题现代 android 开发基本都基于 gradle 属性设置来进行定制化编译,随着项目的迭代,工程结构越发复杂,配置属性越来越多,越来越多的配置使得上手难度越来越大。 解决方案设计一般而言,在 android 开发中,Gradle 属性系…

141个图表,完美展示数据分类别关系!

本文介绍使用Python工具seaborn详细实现分类关系图表&#xff0c;包含8类图141个代码模版。 分类关系图表用于展示数字变量和一个或多个分类变量之间的关系&#xff0c;可以进一步分为&#xff1a;箱形图&#xff08;box plot&#xff09;、增强箱形图&#xff08;enhanced bo…