首页 存档 技术 查看内容

RPC解决了什么问题

2018-3-30 13:00 |来自: 互联网 531 0

摘要: RPC(remote procedure call),远程过程调用,相信大家都不陌生。如果有不清楚的同学可以看下wiki定义: In distributed computing a remote procedure call (RPC) is when a computer program causes a procedure ...

RPC(remote procedure call),远程过程调用,相信大家都不陌生。如果有不清楚的同学可以看下wiki定义:

In distributed computing a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in another address space(commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction.


这段定义提到三点:

  1. 分布式环境。

  2. 写起来就跟调用本地函数一样。

  3. 程序员无需关注与远程的交互细节。


这三点也可以用来描述RPC框架需要解决的问题。


RPC本身并不会涉及什么高深的技术,因此在github上随手一搜,就会发现,RPC库跟网络库一样是造轮子的一大重灾区。


话虽如此,写玩具代码也是程序员的一大乐趣。相信看完这篇文章,你也会加入造RPC库轮子的大军中去。




在进入主题之前,我们首先来消除下二义性。

web开发中也有RPC的概念,与现在比较流行的RESTful相反,是基于HTTP协议设计的一类基于「操作」的API:

GET /operation?id=anId


而小说君接下来要讲的RPC,更多地描述的是「代码」层面的RPC。

比如下面一段逻辑,服务器A处理某个请求时,需要从其他的服务器拿数据,可以这样写:

var data = serviceDelegate.GetData(id);

代码是这样写,GetData内部做的事情实际上就是把服务id、方法id以及参数打包成一个消息发出去,等到其他服务器回过来消息之后,再回调到发起者的相应方法。




三年前,小说君在腾讯参与一款页游项目的开发。可能是因为历史遗留原因,该项目并没有采用RPC。因此作为逻辑狗,代码写起来非常蛋疼。

举个简单的例子,发送一个含有a和b两个参数的请求包这样的简单操作,应用层程序员需要先分配一个请求对象,然后人肉给a和b赋值,再手动调下序列化函数,最后发送。接收包时的操作类似。

如果该项目引入RPC,那发请求就是一行代码,跟调用普通函数的写法一样;收请求则是由框架自动回调一个signature即包参数的函数。应用层程序员根本不需要关注「包」、「序列化」、「反序列化」这些概念,少写不少重复代码。


当然,RPC也并不是尽善尽美,看过《Unix编程艺术》的同学可能对书中批评RPC的章节仍有印象,小说君简单总结一下:

  • RPC接口不具备自我描述性。

  • RPC太容易扩展,容易增加系统复杂度。

  • RPC透明性差,程序员无法直接获知某个RPC接口的调用成本。

  • RPC鼓励程序员视跨机调用为无成本行为。


简单地说,RPC受「人」的因素影响巨大。RPC和本地函数外观一模一样,RPC就会被无节操的程序员扩散在系统各处。

如果只是上层逻辑倒还好,可以通过一定的沙盒机制杜绝级联效应。但是小说君最近在review新接手的框架时就发现,之前的维护者在框架层面不少主流程中用RPC绕来绕去,简直把后来人绕晕。

RPC本意是减轻程序员编码负担,但是如此一来,就完全违背了设计本意。


云风写过一篇博客是「RPC之恶」,其中也提到了一个滥用RPC的例子:系统库内置的sort函数往往需要用户传入comparer,有的程序员就会在comparer中调用RPC,甚至comparer的后续执行还需要RPC的远程返回结果。

这显然是不对的,「流程」获取数据,「算法」处理数据;而不是「算法」执行过程中自行根据「流程」获取数据,再自行处理数据。


不过,排除了「人」的因素之后,RPC带来的收益还是相当明显的,特别对于游戏项目或者应用项目的后端开发来说,服务定义可控,流程可控,即使出现前述问题,要么是能较快定位到问题,要么是不至于给项目带来灾难性影响。

是否在项目中采用RPC,是一个见仁见智的抉择问题。本文接下来就聊聊RPC框架需要解决什么问题,以及如何设计RPC框架。




RPC框架需要解决什么问题?


我们看文章开头提到的三点:

  1. 分布式环境。

  2. 写起来就跟调用本地函数一样。

  3. 程序员无需关注与远程的交互细节。


接下来逐条展开。




第一点,分布式环境,也就是说,RPC框架需要帮程序员做好方法调用到数据的转换,然后再借助网络库发出去;接收侧的网络库收到后将数据推给接收侧的RPC框架,RPC框架再帮程序员做好数据到方法回调的转换。

流程很简单,网络库相关的实现可以参考服务端系列的第一篇文章「 声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除


路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部