重复造轮子系列:分布式rpc框架设计_00
摘要:
本文介绍了分布式框架的简单实现,说明了自己的设计思路,以及RPC的一些具体细节。在文末,贴出一些关于rpc的资料。
0x00:什么是RPC
wiki给出的定义如下:In distributed computing, a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in a different 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.也就是说rpc实际上是这样的一项技术,他使得开发人员能够像调用本地方法一样的调用远程方法。使得我们可以完全解耦服务端和客户端。随着计算资源和网络资源的进步,RPC可以说会变得越来越流行。在我刚开始接触RPC时,我一直在想,既然是远程方法调用,我们之前对于网络服务的获取,不是可以通过http来获取么,随着对于RPC的学习,我发现这两者其实并不冲突,只不过应用的场景不同罢了。可以简单的这么理解,http和rpc作为交通工具,各自有着不同的使用场景,尽管去某个目的地,可能自行车和汽车都能到达,但是我们还是会根据路况和路程来综合考量我们的选择。
0x01:从功能倒推实现
既然我们想设计这样的一款框架,他能够替我们屏蔽掉所有的RPC实现细节,让我们感觉起来就像在使用本地方法调用,那么最终的接口应该看起来像这样的:
(remote-call service-name service-paras)
这样的封装使得客户端丝毫感受不到远程服务的存在,这也就屏蔽掉了RPC的细节,使得客户端能够完全聚焦于业务逻辑,而不用去关心网络通信,服务发现等的问题。但我们知道,计算机编程不是魔法,并不是随便念两句咒语就能真的指挥计算机完成我们想做的事情,框架所做的,只不过是把细节都屏蔽掉了而已。作为框架的实现者,我们需要负责实现这些细节。下面就让我们来分模块的来分析RPC都需要有哪些功能。
- 服务主机的选取:既然服务是在远程主机上实现的,而客户端又不关心具体那台主机为我们实现了这些服务。因此我们需要有一个模块来为我们完成服务主机的选取。我们的服务又想构建成分布式的,那么势必还牵扯到服务主机选择的一些算法。服务选择模块为我们提供这样的功能:
(host,port) = (service-choose service choosen-algs)
- 网络通信部分:在服务端和客户端,涉及到的网络传输就是将客户端的请求服务信息传输到服务端,然后再服务端完成调用,再将结果返回。这样看起来,特别想http的应答响应式服务。仿照JavaEE的httpservlet协议,我们也定义我们的Rpc protocal。将request封装成rpcRequest,将服务器的应答response封装成rpcResponse。同时既然涉及到网路传输,由于网络只能传输字节流,我们肯定还得涉及到对象序列化技术。这样网络部分我们就设计完毕了。
- 服务的具体实现,由于我们选用的java实现,而服务是在服务端完成的。因此我们可以使用java的反射技术来为我们完成服务的具体执行过程。同时,我们还涉及到服务中java对象的具体管理,因此我们选用sping的IoC来为我们自动管理这些服务对象。
这样分析完毕,大致框架基本上清楚了,我们再通过几张图来具体的说明:
首先我们来看一下著名的RPC框架Dubbo的模块图:
我们依次来说下这些模块和我们上面剖析的具体对应:
Provider和Container具体对应我们上面所说的服务具体实现部分,Registry对应我们所说的服务主机的选取模块,而网络服务模块,架构中并没有直接体现,但是肯定是发生在invoke和notify之间。对于这样网络服务软件,我们不妨分层看一下其结构,这样能更清晰的把握整个工作流程。
可以看到整个层次还是非常清晰的,在应用层,我们只能看到看到rpc协议的封装。遵循我们软件设计中的分层原则。
具体技术选型
首先对于网络连接,我们选择netty框架,因为netty的网络连接是非阻塞的,而且为我们的网络编程提供了非常好的抽象。使得我们只需要关注应用层的协议涉及即可。序列化选择Protostuff框架。他为我们提供了非常强大高效的序列化工具。由于我们想将该框架设计成分布式的,我们选择ZooKeeper来为我们管理集群,提供分布式服务。最后,服务端服务对象的自动管理,我们采用sping,该框架的IoC容器为我们提供了非常强大的自动化对象管理功能。