分布式计算场景下,在一台计算机上运行的程序,需要跟另一台计算机上的程序进行交互。从开发角度而言,如果这种交互看起来跟本地函数调用是一模一样的,成本是最低。
因此,RPC设计需要考虑以下三个因素:
1.在本地和远程计算机之间,传递对象。
对象的角色是入参和返回值。这种传递对方的方式叫序列化和反序列化。对象是类的实例化,对象内部有函数和变量。一个对象在生命周期内可以经历多种计算,形成特定的状态,序列化就是把对象转化成一组二进制字节码。把这组字节码发送到远程计算机后,可以直接在远程计算机复制出这个对象。就像《黑客帝国》的密探史密斯先生,伸手到穿越到另一个世界,复制出另一个完全一样的史密斯。
2.远程调用的类定义。
如果把一组二进制码,传递到远程计算机反序列化,远程计算机需要知道这组二进制码的含义。进一步地,对象的作用是传递参数的话,因此不需要有函数,更进一步地,成员变量一律是public ,protected和private是没有意义。这块有两种现实方式:第一种,本地计算机和远程计算机都有被传递的对象的类定义源码; 第二种,非源码方式的定义。
3.远程调用的代理类。
远程调用的形式跟本地调用是一样的,实际上背后的过程不一样,因此需要给远程调用做一次封装,解决背后的不一样的问题,这层封装叫代理,由RPC框架解决。
在这三个因素之外,还有一些次级的问题:服务端和客户端的关系问题,单向还是双向; 服务端的服务注册; 使用哪种传输协议,TCP/UDP,HTTP,HTTP2; 使用哪种序列化方式,xml,json,protobuf, avri, thrift; 是否支持多种语言。
开源RPC框架非常多,从业务角度而言,选择开源框架有几个原则:
1.用的人多。这意味着潜在的坑少,没有大坑,糟糕的坑大概率被填完了。好招人,懂的人比较多。普适多种业务,在不同场景下都经历了考验。
2.社区稳定强大。框架可以持续活下去,你的技术投入不会打水漂。框架可以持续进化下去,应对新业务新趋势。
3.支持多种语言。公司内部不同业务使用不同语言,可以在RPC上交互。