第01篇 什么是远程调用

1. 什么是远程调用呢

通常我们将其简称为 RPC(Remote Procedure Call)即“远程过程调用”,简单来说就是调用方和被调用方不在一个机器上,我们可以比对着“本地过程调用”去理解这一概念。

1)本地过程调用

本地过程调用,其实就是调用方和被调用方在同一个机器上、甚至是同一个进程中,这样它们相互调用起来相对“远程过程调用”就容易太多了。

比如我们在项目的某个类中写了个 public int add(int a, int b) 的方法, 然后我们在这个项目的其它方法中去调用它,这样的调用方式就是“本地过程调用”。或者我们调用一些操作系统内核函数时,虽然不是同一个进程中,但也属于同一个机器上,也是“本地过程调用”。

2)远程过程调用

而与“本地过程调用”不同的是,“远程过程调用”的调用双方并不在同一个机器上,甚至可能相隔万里。这种情况下,就需要借助网络去传输调用过程中的参数信息及返回结果等信息,这个过程就要比“本地过程调用”繁琐很多了。

当然在绝大多数情况下,我们不会自己去实现 RPC 的数据封装和网络传输,而是直接使用 RPC 框架,在框架中已经帮我们做了这些繁琐事情,可以让我们使用起来能和“本地过程调用”有相同的感受。

2. 为什么要使用 RPC

为什么要使用 RPC 呢,直接把各种功能写在同一个系统中不就好了?那么,假设我们要写一个“京东”的订单系统,当用户挑选好商品后,由系统来创建对应的订单,此时一个简化的流程如下:

创建订单

由上图可以看到,我们创建订单时,需要锁定商品的库存,以此来防止商品被超卖。并且从上图也可以明显看出,库存锁定方法也是由“订单系统”自己实现的,所以直接调用自身的库存锁定的方法即可。

不过实际情况并不会这么做,而是会将这些功能拆分到多个系统中,比如上面的功能可以拆分成“订单系统”和“库存系统”中,然后通过 RPC 来做系统之间的调用。那么,到底是什么原因导致我们要拆分系统呢,如果非要把所有功能写在一个系统中会怎么样?

1)代码维护成本

当系统功能非常多时,它的代码量也是巨大的,这也意味着会有很多人参与维护这些代码。当几十人甚至几百人去维护同一份代码,就会有非常多的代码合并冲突要处理,并且经常会出现我改动了你的代码,你又影响了我的代码逻辑,这样导致你我的代码都得重新测试,会极大增加测试人员的工作量。而且每次上线时可能会涉及到几十个功能,一旦某个小功能出问题,整个系统的所有功能都要被迫回滚,这样每次上线对我们来说都是一种巨大的挑战,也会让系统面临巨大的风险。

所以单从代码维护的角度上,就足以说明拆分系统的必要性。我们将系统功能梳理拆分到各个小系统中,每个小系统有两三个人维护就足够了,这样每个系统的代码各自独立,各自有自己的机器,上线完全可以根据自己的节奏来。只有合理的拆分系统,才能保证团队整体的开发效率,否则系统太过臃肿导致后续难以维护。

2)资源的利用率

当用户体量不断提升时,或者做活动搞促销时,系统中的某些功能模块的压力会增大,这时候我们就需要对机器进行扩容。由于全部的业务功能都是同一个系统中,有些功能对 CPU 要求较高,有些功能对内存使用较多,还有些功能对磁盘 I/O 开销较大,这样我们很难实现精准扩容。并且一些核心功能在促销时流量会有比较大的增长,而有些非核心的功能的流量增长可能不会有那么大,扩容时只能按照核心服务要求的容量标准来扩,但实际上这些增长的容量对那些非核心服务来说可能是浪费的。

另外还有一点,有些情况下我们是允许某些功能暂时不可用的,也就是说可以容忍局部的不可用但整体可用。比如因为我们做活动导致流量突增,导致登录功能会出现较高的延迟,但是其它功能不能受影响,也就是我们可以牺牲小部分用户的体验,而保障整体的可靠性。所以将系统拆分也是我们保证系统稳定的一种重要手段。

3. 一次 RPC 经历过程

现在我们就把之前下单的功能拆分到“订单系统”和“库存系统”中,并通过 RPC 进行系统间的调用,此时流程大致如下:

创建订单

由上图可以看到,当“订单系统”收到商品的建单请求后,会通过 RPC 调用“库存系统”对商品库存进行锁定,当库存锁定成功后,再继续完成订单的创建。

既然我们决定拆分系统并使用 RPC 调用,那么我们就再了解下 RPC 的调用过程,看看我们的数据是如何被处理并传送到了另一台机器上的,整个过程如下图所示:

一次 RPC 调用过程

从上图可以看到一次 RPC 调用的过程是非常复杂的,在调用过程中会通过网络传输数据(使用 TCP 或 UDP),但此时我们突然想起来 HTTP 调用也是通过网络进行调用,并且调用方和被调用方也不在一台机器上,那么 RPC 调用和 HTTP 调用相比的区别是什么呢?我们直接使用 HTTP 进行系统间的调用不是也挺好吗,为什么又要提出一个 RPC 的概念呢?

1)使用场景不同

HTTP 多用于客户端和服务端之间的调用,比如浏览器、IOS客户端、安卓客户端等,它们大多通过 HTTP 调用服务端,而服务端之间大多采取 RPC 的形式进行调用。当然了,这也并不绝对,我们也完全可以使用 RPC 做前后端之间的调用,也可以使用 HTTP 做服务端之间的调用。

2)传输格式不同

使用 HTTP 调用时,使用的是 HTTP 协议(HTTP 协议有 HTTP1.0、HTTP1.1 和 HTTP2.0,感兴趣的可以自行百度)。而使用 RPC 调用时,可以自由的选择不同协议,也可以自定义协议,甚至也可以直接使用 HTTP 协议。不过 HTTP 协议由于加上了各种消息头,导致消息数据会比较长,而 RPC 调用一般都比较追求传输的性能,所以都会选择一些数据精简的协议格式,这样传输的数据量小,速度会更快些。

3)封装程度不同

上面我们说过 HTTP 也可以做服务端之间的调用,那么为什么不使用它而使用 RPC 呢?或者说使用 RPC 的优势在哪?

原因主要有两个方面,一方面是后端系统之间使用 HTTP 进行调用并不方便,即使有 HttpClient 这样的工具,依然需要我们自己去做一些额外的处理。而 RPC 可以让我们像调用本地服务一样调用远程服务,我们无需关心其中的细节,代码也会看起来更加简洁和美观。这其实就是 RPC 帮我们做了更多的封装,更方便于后端系统之间的相互调用,可以看作 RPC 是在 HTTP 的基础上又做了一层封装。

而另一方面刚刚在讲传输格式时也提过,就是 HTTP 协议比较臃肿,导致我们每次调用时传输的数据会比较多,从而影响了调用的性能。而使用 RPC 时我们可以自由选择协议格式,这样我们会选择一些较为精简的协议格式,以此来提高网络传输效率,也提高了调用的性能。

4. 成熟的 RPC 框架

上面我们说的 RPC 中的处理细节并不需要我们自己实现,目前已经有成熟的 RPC 框架可以供我们选择,如下图所示用虚线圈起来的部分是由 RPC 框架来提供的。

RPC框架

1)最初由阿里开源的 Dubbo 框架

Dubbo 可能很多人都听说过,它是由阿里最初于 2011 年开源的一款 Java RPC 框架,后来停止维护了一段时间后又重启,在 2018 年时阿里将其贡献给了 Apache 软件基金会,后来在 2019 年成为 Apache 的顶级项目 Apache Dubbo。

在网络上 Apache Dubbo 的相关资料很丰富,其使用也比较方便,并且可以和 Spring 框架集成。而在其功能方面,Apache Dubbo 除了能为我们提供基本的 RPC 功能外,它还支持服务注册与发现、服务治理、注册中心等重要功能(这些功能的作用后面我们再统一解释下),这也意味着 Apache Dubbo 不仅仅是一个 RPC 框架,它更是一个服务治理框架(什么是服务治理我们后面再讲)。

2)最初由 facebook 开源的 thrift 框架

Thrift 最初由 facebook 开发,并在 2007 年贡献给了 Apache 软件基金会,成为 Apache 的顶级项目 Apache Thrift。

与 Dubbo 不同的是,虽然 Thrift 由 Java 语言编写,但它是一款跨语言的 RPC 框架。用户通过 Thrift IDL(接口定义语言)描述接口和参数,然后通过 Thrift 提供的编译器并根据我们需要,生成不同语言的代码,例如: C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk 等。

Thrift 的历史虽然悠久,但是网络上能深入讲解 Thrift 的文章几乎没有,大多都是停留在 Thrift IDL 语法及 Thrift 结构简单讲解的层次上。

3)谷歌开源的 gRPC 框架

Google发布的开源RPC框架,高性能、开源、将移动和HTTP/2放在首位的通用的RPC框架,基于HTTP/2, netty4.1, proto3, 拥有非常丰富而实用的特性,堪称RPC 框架的典范。

但它本身它不是分布式的,所以要实现上面的框架的功能需要进一步的开发。

4)Hessian

是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 基于HTTP协议,采用二进制编解码。
利用java.rmi包实现,基于Java远程方法协议(Java Remote Method Protocol) 和java的原生序列化。

gRPC dubbo thrift Hessian
支持语言 ---- ---- ---- ----
服务治理 ---- ---- ---- ----
资料数量 ---- ---- ---- ----
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350