在上一篇分布式系统系列中《 分布式系统中的必备良药 —— 服务治理 》中阐述了服务治理的一些概念,那么与服务治理配套的必然会涉及到 RPC 框架。在当前互联网的大背景下,RPC 的运用应该大家或多或少都有涉及,国内外的 RPC 框架也是百花齐放。那么各个 RPC 框架各自有什么特点,另外 RPC 的核心点又是哪些,我们该如何去选择是本文需要讲述的内容。本文会围绕. Net 技术栈来展开,暂不讨论诸如 dubbo 之类对. Net 不太友好的框架。
1.Google.gRpc( github.com/grpc/grpc )
大名鼎鼎的 Google 出品的 RPC 框架,基于 Http2 设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量。使用的时候需要通过定义 proto 文件生成客户端和服务端代码,可以跨平台(客户端和服务端生成代码时使用不同的语言)。如果大家已经被微软宠惯了,那么是不太习惯以一个纯 txt 方式编辑这个 proto 文件的,毕竟全部需要手打 ╮(╯_╰)╭
2.Facebook.Thrift( github.com/apache/thri… )
同样是大厂 Facebook 出品的 RPC 框架,使用方式和 gRpc 类似,需要通过定义. thrift 文件生成客户端和服务端代码,可以跨平台(客户端和服务端生成代码时使用不同的语言)。Thrift 的缺点是无法生成 async,await,Task<T> 之类的泛型代码,这个对于当下大背景来说有一定的局限性(如果有小伙伴知道如何解决此问题,感谢赐教)。Thrift 最大的特点是 5 种适用不同场景的服务模型,一图胜千言,直接上图,见图 1:
【图 1】
但是遗憾的是 Apache 在. Net 下提供的实现并不是上面的 5 种模式,仅仅 3 种(TSimpleServer、TThreadPoolServer、TThreadedServer),特别是在 Java 下大规模宣传的 NIO 模式没有提供实现。
3.Orleans( dotnet.github.io/orleans/ )
这是微软在 2015 开源的构建分布式应用的框架。(什么意思?那它是 RPC 框架么?)我想这是大部分对 Orleans 不熟悉的同学的疑问,实际上 Orleans 的层次比 RPC 框架更高,它不仅仅解决了远程调用问题,其内部还包含了服务发现、负载均衡、高可用等一些处理机制。一般用 Akka(有. net 版本 Akka.net)和它对标,都是基于 Actor 模型设计的分布式框架,顺手附上一篇经典的对比文章: github.com/akka/akka-m… 。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 等。对于对性能十分执着的小伙伴们,这里有一份转载的基准测试报告,连接附上: www.cnblogs.com/shanyou/p/3… 。大部分的框架都会序列化这层做成可适配的,相对网络协议,对序列化的个性化迫求是更强烈的。
测试环境如下:
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】
这个是我网上找到的一篇性能相关的文章,大家可以参考一下: blog.csdn.net/jek123456/a… 。
归根到底,大家在使用之前还是需要结合自己的实际情况,放到实际的场景去测一把,看看效果。下面奉上替大家迈出第一步的 Demo,大家可以进行进一步的深入研究。
本文相关的测试数据 excel 在此: github.com/ZacharyFan/…
本文相关的 Demo 地址在此: github.com/ZacharyFan/…
作者: Zachary_Fan
来源: https://juejin.im/entry/5a36f66751882506146eff12