MiniRpc 实现Rpc

完成了上一篇说的网络层,我终于可以实现client端和server端的互联了。那么现在是时候动手实现自己的Rpc框架了。

ProtoBuf

google开源的序列化框架,在开始实现Minirpc之前就已经准备使用它了。不光是实现高效使用方便的序列化/反序列化协议,它还提供了实现rpc的接口,看来google一开始就是打算在它的上面实现rpc框架的,当然就是现在的gRpc。

ProtoBuf的使用我就不多说,官网有参考文档。既然协议如此高效,我还稍微看了下它的编码方式,最主要的是varint编码和ZigZag编码,看来protobuf为了节省传输数据的大小无所不用其极啊。

RpcConnection

这应该是实现中最重要的类,管理着server端的rpc连接。目前有缺陷的地方时暂时还没有实现长连接,这里写下准备实现长连接的设计。

为了实现长连接,在client端需要根据不同server的ip地址建立几条少数的链接,在server端,需要使用心跳包来维持建立的长连接,即使断开无效链接。另外,如果链接数过多,可以使用时间轮的方法来踢掉长久没有响应的空闲链接。

RpcConnection在代码中是使用智能指针管理的,这里就有所有权的关系,就是确定谁拥有RpcConnection。在实现上我犯过一个小错误,就是在将普通指针换成智能指针的过程中,混用了普通指针和智能指针,导致测试运行程序的时候core dump了,显示double free。这里需要注意,资源要全部交给智能指针管理,不能自己再用裸指针了。

连接池

由于现在实现中都是短链接,频繁的断开建立链接需要消耗很多的资源和不少的时间,在server端,我使用了连接池。如果新的连接到来,就从连接池中取出一个空闲连接,连接关闭后将其放回连接池。

负载均衡

一开始没有设计多线程,仅仅在server端只有一个工作线程。最后面在服务器上运行测试的时候,发现性能比较差,才决定在服务端加上多线程的。

最后面的架构是是一个IO线程负责accept新的连接,将新到来的连接按照简单的round-robin算法用线程安全的接口放入四个工作线程,此后,连接就由工作线程管理了。这样改变了之后,性能有所提高(但是还是不满意,后面还要继续优化)。

Reference

ProtoBuf文档