分布式系统中的必备良药 —— RPC
阅读目录
一、前言
在上一篇分布式系统系列中《分布式系统中的必备良药 —— 服务治理》中阐述了服务治理的一些概念,那么与服务治理配套的必然会涉及到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
如果你想及时得到个人自写文章的消息推送,欢迎扫描下面的二维码~。

分布式系统中的必备良药 —— RPC的更多相关文章
- 分布式系统中的RPC请求经常出现乱序的情况 写一个算法来将一个乱序的序列保序输出
分布式系统中的RPC请求经常出现乱序的情况. 写一个算法来将一个乱序的序列保序输出.例如,假设起始序号是1,对于(1, 2, 5, 8, 10, 4, 3, 6, 9, 7)这个序列,输出是: 1 ...
- 将目录下面所有的 .cs 文件合并到一个 code.cs 文件中,写著作权复制代码时的必备良药
将目录下面所有的 .cs 文件合并到一个 code.cs 文件中,写著作权复制代码时的必备良药 @echo off echo 将该目录下所有.cs文件的内容合并到一个 code.cs 文件中! pau ...
- 分布式系统中session一致性问题
业务场景 在单机系统中,用户登陆之后,服务端会保存用户的会话信息,只要用户不退出重新登陆,在一段时间内用户可以一直访问该网站,无需重复登陆.用户的信息存在服务端的 session 中,session中 ...
- 如何在高并发分布式系统中生成全局唯一Id
月整理出来,有兴趣的园友可以关注下我的博客. 分享原由,最近公司用到,并且在找最合适的方案,希望大家多参与讨论和提出新方案.我和我的小伙伴们也讨论了这个主题,我受益匪浅啊…… 博文示例: 1. ...
- 【分布式】Zookeeper在大型分布式系统中的应用
一.前言 上一篇博文讲解了Zookeeper的典型应用场景,在大数据时代,各种分布式系统层出不穷,其中,有很多系统都直接或间接使用了Zookeeper,用来解决诸如配置管理.分布式通知/协调.集群管理 ...
- 分布式系统中一些主要的副本更新策略——Dynamo/Cassandra/Riak同时采取了主从式更新的同步+异步类型,以及任意节点更新的策略。
分布式系统中一些主要的副本更新策略. 1.同时更新 类型A:没有任何协议,可能出现多个节点执行顺序交叉导致数据不一致情况. 类型B:通过一致性协议唯一确定不同更新操作的执行顺序,从而保证数据一致性 2 ...
- 如何在高并发分布式系统中生成全局唯一Id(转)
http://www.cnblogs.com/heyuquan/p/global-guid-identity-maxId.html 又一个多月没冒泡了,其实最近学了些东西,但是没有安排时间整理成博文, ...
- (转)如何在高并发分布式系统中生成全局唯一Id
又一个多月没冒泡了,其实最近学了些东西,但是没有安排时间整理成博文,后续再奉上.最近还写了一个发邮件的组件以及性能测试请看 <NET开发邮件发送功能的全面教程(含邮件组件源码)> ,还弄了 ...
- 分布式系统中生成全局ID的总结与思考
世间万物,都有自己唯一的标识,比如人,每个人都有自己的指纹(白夜追凶给我科普的,同卵双胞胎DNA一样,但指纹不一样).又如中国人,每个中国人有自己的身份证.对于计算机,很多时候,也需要为每一份数据生成 ...
随机推荐
- php读取excel文档内容(转载)
入到数据库的需要,php-excel-reader可以很轻松的使用它读取excel文件,本文将详细介绍,需要了解的朋友可以参考下 php开发中肯定会遇到将excel文件内容导入到数据库的需要,ph ...
- OpenCV二维Mat数组(二级指针)在CUDA中的使用
CUDA用于并行计算非常方便,但是GPU与CPU之间的交互,比如传递参数等相对麻烦一些.在写CUDA核函数的时候形参往往会有很多个,动辄达到10-20个,如果能够在CPU中提前把数据组织好,比如使用二 ...
- mapreduce解析执行sql流程
样例准备 编号 姓名 性别 班级编号 1 name_1 male 1 2 name_2 female 2 3 name_3 male 3 4 name_4 female 4 5 name_5 male ...
- app.config 配置多项 配置集合 自定义配置(3)
再说说利用app.config配置多个自定义的方法.先看这个例子:美国家庭Simpson的家里有父亲母亲和三个儿女,而中国的老王只有独生子女.结构如下: <?xml version=" ...
- Spring JDBC 示例
在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等.但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQL 语句,处理异常, ...
- 从cdn说起
为什么要使用cdn 雅虎军规有一条规则建议我们是用cdn.随便在网上搜索,可以找到使用的cdn的好处. 再次强调第一条黄金定律,减少网页内容的下载时间.提高下载速度还可以通过CDN(内容分发网络)来提 ...
- 1455:An Easy Problem
传送门:http://noi.openjudge.cn/ch0406/1455/ /-24作业 //#include "stdafx.h" #include<bits/std ...
- 运行java web项目时报错:Several ports (8005, 8080, 8009) required
运行java web项目时报错:Several ports (8005, 8080, 8009) required 如下图 之所以报上面的错误是因为安装Tomcat的时候,已经把端口8005,8080 ...
- JS构造函数模式
构造函数是可以创建特定类型对象的函数,可以接受参数定义函数成员.如果之前做过java比较好理解,举个例子: function exampleFunction(arg1, arg2, arg3){ th ...
- 【SSM之旅】Spring+SpringMVC+MyBatis+Bootstrap整合基础篇(一)项目简介及技术选型相关介绍
试水 一直想去搭建个自己的个人博客,苦于自己的技术有限,然后也个人也比较懒散.想动而不能动,想动而懒得动,就这么一直拖到了现在.总觉得应该把这几年来的所学总结一番,这样才能有所成长. 不知在何时,那就 ...