优点
-
交互方式简单,一个service就是一个interface。client/server间的交互协议容易统一。
一般成熟的公司都自己维护的RPC框架(比如百度的sofa-pbrpc, google的gRpc,使用它们非常简单,只需要一个proto文件就可以描述两边的协议交互。因为描述文件(proto文件)是确定的,所以两边容易保持一致,基本不会出错。而且大多可用RPC框架生成所有interface的封包、解包代码,用户只需要调调函数即可。 -
测试方便。
大多RPC框架是跨语言的,所以可用更方便的脚本语言(如python)写测试程序,模拟与C/C++程序的交互。
缺点
-
多了一层间接性,出现网络问题时,debug比较困难。
-
交互方式单一,不能进行复杂的多模块之间的协议交互。
RPC的描述方式较单一,一般是一应一答。有一些场景没法用RPC描述,比如有一个服务需要协调多个模块、服务端主动发通知给客户端。 -
异常处理困难。
- 如果是同步调用,长时间阻塞怎么办?
- 如果是异步调用,长时间没有得到结果怎么办?
- 如果判断failure(网络不通、参数不对、心跳超时)?
可以重试吗?调用语意:至多一次、至少一次、恰好一次?
一般RPC执行的结果有三种状态:成功、失败、超时(未知状态)。当发生超时时,不知道对端server是收到请求且已经执行了,还是没收到请求,此时只能通过不断读取之前操作的状态来验证RPC操作是否成功,然后采取相应的操作。但是如果每次调用RPC都要做各种各样的异常处理,代码会不会变得冗长哆嗦?
还有一种处理方法是将操作设计成一种”幂等”操作,就是说,执行多次与执行一次的结果是一样的,比如说覆盖写操作。但是某些客户操作不方便表示成幂等操作,这时候应该怎么处理呢?