长途进程挪用(Remote Procedure Call,RPC)是一个计较机通信协议。该协议答允运行于一台计较机的措施挪用另一台计较机的子措施,而措施员无需特别地为这个交互浸染编程。RPC的主要方针是让构建漫衍式应用越发容易,在提供强大的长途挪用本领的同时不损失当地挪用的语义的简捷性。
趁实习前的这段业余时间,我实现了一个轻量级的漫衍式RPC框架,名字叫做 buddha,代码量不大,可是麻雀虽小却五脏俱全。本篇文章将一步步阐发buddha的设计、框架组件的拆解以及需要思量的因素。
序列化与反序列化
在网络中,所有的数据都将会被转化为字节举办传送,所以在代码层面上,一个RPC框架需要实现特命名目标数据与字节数组之间的彼此转化。像Java已经提供了默认的序列化方法,可是假如是在高并发的场景下,利用Java原生的序列化方法大概会碰着机能瓶颈。于是,呈现了很多开源的、高效的序列化框架:如Kryo、fastjson和Protobuf等。buddha今朝支持Kryo和fastjson两种序列化框架。
TCP拆包、粘包
由于TCP只体贴字节约,并不知晓上层的数据名目。假如客户端应用层一次要发送的数据过大时,TCP会将该数据举办解析传送,因此在处事端需要举办粘包处理惩罚(由TCP来担保数据的有序性);假如客户端一次要发送的数据量很小时,TCP并不会顿时把数据发送出去,而是将其存储在缓冲区,当到达某个阈值的时候再发送出去,因此在处事端需要举办拆包的事情。
通过以上阐明,我们相识了TCP粘包可能拆包的原因,办理这个问题的要害在于向数据包添加界线信息,常用的要领有如下三个。
buddha回收第一种方法来办理TCP拆包、粘包的问题。
BIO与NIO
BIO往往用于经典的每毗连每线程模子,之所以利用多线程,软件开发,是因为像accept()、read()和write()等函数都是同步阻塞的,软件开发,这意味着当应用为单线程且举办IO操纵时,假如线程阻塞那么该应用一定会进入挂死状态,可是实际上此时CPU是处于空闲状态的。开启多线程,就可以让CPU去为更多的线程处事,提高CPU的操作率。可是在活泼线程数较多的环境下,回收多线程模子回带来如下几个问题。
利用线程池的方法办理前两个问题,可是线程切换带来的开销照旧存在。所以在高并发的场景下,传统的BIO是无能为力的。而NIO的重要特点是:读、写、注册和吸收函数,在期待停当阶段都长短阻塞的,可以当即返回,这就答允我们不利用多线程充实操作CPU。假如一个毗连不能读写,可以把这个事件记录下来,然后切换到此外停当的毗连举办数据读写。在buddha中,Netty被用来编写布局越发清晰的NIO措施。
处事注册与发明
在实际应用中,RPC处事的提供者往往需要利用集群来担保处事的不变性与靠得住性。因此需要实现一个处事注册中心,处事提供者将当前可用的处事地点信息注册至注册中心,而客户端在举办长途挪用时,先通过处事注册中心获取当前可用的处事列表,然后获取详细的处事提供者的地点信息(该阶段可以举办负载平衡),按照地点信息向处事提供者提倡挪用。客户端可以缓存可用处事列表,当注册中心的处事列表产生改观时需要通知客户端。同时,当处事提供者变为不行用状态时也需要通知注册中心处事不行用。buddha利用ZooKeeper实现处事注册与发明成果。
代码实现
buddha是我进修验证RPC进程中降生的一个轻量级漫衍式RPC框架,代码放在了 GitHub。
参考