一、前言

  在上一篇分布式系统系列中《分布式系统中的必备良药 —— 服务治理》中阐述了服务治理的一些概念,那么与服务治理配套的必然会涉及到RPC框架。在当前互联网的大背景下,RPC的运用应该大家或多或少都有涉及,国内外的RPC框架也是百花齐放。那么各个RPC框架各自有什么特点,另外RPC的核心点又是哪些,我们该如何去选择是本文需要讲述的内容。本文会围绕.Net技术栈来展开,暂不讨论诸如dubbo之类对.Net 不太友好的框架。

 

二、成熟的解决方案

  1.Google.gRpc(https://github.com/grpc/grpc

    大名鼎鼎的Google出品的RPC框架,基于Http2设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量。使用的时候需要通过定义proto文件生成客户端和服务端代码,可以跨平台(客户端和服务端生成代码时使用不同的语言)。如果大家已经被微软宠惯了,那么是不太习惯以一个纯txt方式编辑这个proto文件的,毕竟全部需要手打 ╮(╯_╰)╭

  2.Facebook.Thrift(https://github.com/apache/thrift

    同样是大厂Facebook出品的RPC框架,使用方式和gRpc类似,需要通过定义.thrift文件生成客户端和服务端代码,可以跨平台(客户端和服务端生成代码时使用不同的语言)。Thrift的缺点是无法生成async,await,Task<T>之类的泛型代码,这个对于当下大背景来说有一定的局限性(如果有小伙伴知道如何解决此问题,感谢赐教)。Thrift最大的特点是5种适用不同场景的服务模型,一图胜千言,直接上图,见图1:

                    【图1】

     但是遗憾的是Apache在.Net下提供的实现并不是上面的5种模式,仅仅3种(TSimpleServer、TThreadPoolServer、TThreadedServer),特别是在Java下大规模宣传的NIO模式没有提供实现。

  3.Orleans(http://dotnet.github.io/orleans/

    这是微软在2015开源的构建分布式应用的框架。(什么意思?那它是RPC框架么?)我想这是大部分对Orleans不熟悉的同学的疑问,实际上Orleans的层次比RPC框架更高,它不仅仅解决了远程调用问题,其内部还包含了服务发现、负载均衡、高可用等一些处理机制。一般用Akka(有.net版本 Akka.net)和它对标,都是基于Actor模型设计的分布式框架,顺手附上一篇经典的对比文章:https://github.com/akka/akka-meta/blob/master/ComparisonWithOrleans.md 。Orleans最大的特点就是微软一向的风格,高度封装,提高生产力。面向OOP的设计,便于使用,大家可以在文末下载Demo感受一下,手感和WCF比较类似。

  4.WCF

    这应该是.net系下做分布式系统开发中的RPC标配了,随着.net framework3.5在2007年推出,可谓功能丰富,而且支持的协议相比其它框架也是最多(没有之一)。

  5.WebApi

    这是随着VS2012一起推出的REST化API的一项web服务。近几年随着整个大环境的变化,逐渐有代替WCF的趋势。跨平台(特别是针对移动端有很大优势)、便于开放共享和测试是他相对WCF的最大优势。

 

三、剖析

   上面的这些框架说不上孰优孰劣,都有各自适用的场景。那么我们来刨析一下如果要选择哪个RPC框架更适合的话从何处入手。一个RPC框架核心的概念是下面几个:

网络协议:

  这是RPC框架的核心,面向什么协议去设计,基本上也已经决定了框架最理想的适用场景了。协议又分为2个大类,分别对应OSI七层模型的应用层(http协议、ftp协议等)和传输层(tcp协议、udp协议)。这其中的协议又有各自的特点,这里就不展开说了。当然有些框架将协议这层做成可适配的,比如WCF(不同协议)、thrift(同协议不同实现),那么他们的覆盖场景肯定就更多,但是相应的框架的实现复杂度肯定也是相应增加,需要考虑是否能接收这带来的额外成本。

 

 序列化方式:

  序列化一般从3个维度去考虑,数据大小、可读性、传输效率(序列化反序列所消耗的时间)。属于可读性较好的序列化比如Json;属于数据压缩比比较好的序列化比如Protobuf;属于传输效率高的序列化比如MessageShark、MessagePack、Protobuf等。对于对性能十分执着的小伙伴们,这里有一份转载的基准测试报告,连接附上:https://www.cnblogs.com/shanyou/p/3294201.html 。大部分的框架都会序列化这层做成可适配的,相对网络协议,对序列化的个性化迫求是更强烈的。

 

四、性能测试

测试环境如下:

  CPU:I5-4300U 1.90GHz  2.50GHz

  内存:8G

  策略:10000次调用发送封装world字符串的对象HelloRequest,并等待接收返回封装Hello world字符串的HelloReply对象。

  网络:数据较小+本地调用,网络不是问题。想进一步测试局域网和大数据的可以基于文末的Demo项目自行改造。

  这里需要提一下,WCF的测试使用了http和tcp2种常见的模式,针对webapi的访问使用了HttpClient和HttpWebRequest2种方式。另外值得注意的是,由于Thrift和HttpWebRequest不支持多线程复用同一个实例,故在测试中都是使用每次实例化的方式进行(包括线程数1的时候)。

  由于数据比较多,直接付上2个动图,想进一步分析的可以在文末下载excel自行解决~。见图2,图3:

                  【图2】

                  【图3】

  

五、结语

  这个是我网上找到的一篇性能相关的文章,大家可以参考一下:http://blog.csdn.net/jek123456/article/details/53395206

  归根到底,大家在使用之前还是需要结合自己的实际情况,放到实际的场景去测一把,看看效果。下面奉上替大家迈出第一步的Demo,大家可以进行进一步的深入研究。

 

 

本文相关的测试数据excel在此:https://github.com/ZacharyFan/RpcTest/raw/master/PerfTest.xlsx

本文相关的Demo地址在此:https://github.com/ZacharyFan/RpcTest

 

 

 

作者:Zachary_Fan
出处:http://www.cnblogs.com/Zachary-Fan/p/rpc_overview

 

 

 

如果你想及时得到个人自写文章的消息推送,欢迎扫描下面的二维码~。

版权声明:本文为Zachary-Fan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:http://www.cnblogs.com/Zachary-Fan/p/rpc_overview.html