近期开始研究分布式架构,会涉及到一个最核心的组件:RPC(Remote Procedure Call Protocol)。这个东西的稳定性与性能,直接决定了分布式架构系统的好坏。RPC技术,我们的产品中其实早就已经应用。但是产品中经常出现访问失败等错误,在没有细致研究的情况下,大家怀疑是选用的RPC组件不稳定引起。今天也借这个机会给这个组件正名一下吧。
选型的思路很简单,先baidu找业界最有名的RPC框架,看各种牛人的的对比分析,然后到github上搜索排名和评价靠前的组件,确定一个选型的大致范围,然后进行一轮测试。当然,我们是有特性要求的:
1.最好支持TCP、HTTP两种通讯协议。即使不支持也可以扩展,或者集成两种RPC组件。
2.最好支持异步、同步两种调用方式。
3.性能要尽可能的好。
4.通讯层最好要有失败重试的机制或者类似的补偿机制。
5..net技术路线。
经过筛选,大致确定了5个组件:Thrift、gRPC、Halibut、SCS、Shuttler.net(这是按照知名度排序的)。前两个大家都很熟,后3个比较陌生吧。其中Halibut是Octopus deploy产品中的组件,已经在各种场景中验证过了,对其也寄予一定的厚望(Octopus deploy是自动化部署的产品,微软也在用,是个好东西)。
我的测试方法有些特殊,分为本机和局域网两种网络环境测试(我们的局域网是无线。300M带宽?好像是!)。每种环境在细分为两种场景:无限制、加入10MS延迟和1%丢包。
Thrift情况如下:
单连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试79.1 0.0 10879.9 0.0 3816.1 0.0 8221.7 0.0 第二次测试83.1 0.0 10613.9 0.0 3410.8 0.0 9189.4 0.0 第三次测试80.6 0.0 12221.1 0.0 3726.1 0.0 9662.5 0.0 平均80.9 0.0 11238.3 0.0 3651.0 0.0 9024.5 0.0 每次访问
新建连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试81.6 0.0 19414.9 0.0 3298.6 0.0 13124.0 0.0 第二次测试83.1 0.0 22372.1 0.0 3200.1 0.0 13680.2 0.0 第三次测试82.1 0.0 21589.0 0.0 3958.9 0.0 15757.5 0.0 平均82.2 0.0 21125.3 0.0 3485.9 0.0 14187.2 0.0
gRPC情况如下:
单连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试200.8 0.0 16899.8 0.0 3990.4 0.0 9199.9 0.0 第二次测试200.2 0.0 18200.1 0.0 4099.9 0.0 9200.1 0.0 第三次测试200.4 0.0 16801.0 0.0 3800.2 0.0 9599.6 0.0 平均200.5 0.0 17300.3 0.0 3963.5 0.0 9333.2 0.0 每次访问
新建连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试20522.1 0.0 66560.1 0.0 41991.2 0.0 38106.0 0.0 第二次测试20713.1 0.0 51348.0 0.0 40517.2 0.0 41988.8 0.0 第三次测试20751.5 0.0 56108.4 0.0 42404.0 0.0 52477.6 0.0 平均20662.2 0.0 58005.5 0.0 41637.5 0.0 44190.8 0.0
Halibut情况如下:
单连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试75.1 0.0 15593.3 0.0 1056.6 0.0 13457.4 0.0 第二次测试83.1 0.0 16775.7 0.0 775.9 0.0 9023.0 0.0 第三次测试81.6 0.0 16857.4 0.0 891.4 0.0 10739.2 0.0 平均79.9 0.0 16408.8 0.0 908.0 0.0 11073.2 0.0 每次访问
新建连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试1237.4 0.0 46431.4 0.0 17210.6 0.0 25839.7 0.0 第二次测试1237.9 0.0 44134.8 0.0 10440.8 0.0 34425.2 0.0 第三次测试1232.4 0.0 43727.5 0.0 22320.3 0.0 26654.1 0.0 平均1235.9 0.0 44764.6 0.0 16657.2 0.0 28973.0 0.0
SCS情况如下:
单连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试67.0 0.0 15465.6 0.0 685.6 0.0 7179.0 0.0 第二次测试68.0 0.0 18709.0 0.0 819.1 0.0 11511.9 0.0 第三次测试69.0 0.0 14791.2 0.0 703.3 0.0 7319.3 0.0 平均68.0 0.0 16321.9 0.0 736.0 0.0 8670.1 0.0 每次访问
新建连接本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试74.1 0.0 20980.5 0.0 757.4 0.0 8978.9 0.0 第二次测试70.0 0.0 22169.9 0.0 770.6 0.0 10990.9 0.0 第三次测试77.6 0.0 16133.7 0.0 1019.4 0.0 14943.6 0.0 平均73.9 0.0 19761.4 0.0 849.1 0.0 11637.8 0.0
Shuttler.net情况如下:
Shuttler是支持TCP和HTTP两种协议的,但是TCP的错误太多了,我就不贴了
每次访问
新建连接(HTTP)本机调用:100次耗时(毫秒)局域网调用:100次耗时(毫秒)无限制丢包率:1%,延迟:10ms无限制丢包率:1%,延迟:10ms响应时间失败次数响应时间失败次数响应时间失败次数响应时间失败次数第一次测试46.5 0.0 46950.1 0.0 3062.8 0.0 37665.3 0.0 第二次测试40.5 0.0 42380.0 0.0 2016.0 0.0 42242.0 0.0 第三次测试39.5 0.0 47681.7 0.0 2080.4 0.0 35739.7 0.0 平均42.2 0.0 45670.6 0.0 2386.4 0.0 38549.0 0.0
实际环境中,肯定是局域网环境,所以我把局域网部分的结果统计了一下。因为失败次数都为0,所以只统计了耗时。
项目(100次调用响应时间MS,局域网环境)ThriftThrift(Teld)gRPCHalibutSCSShuttler.net单链接无限制3651.0 3774.8 3963.5 908.0 736.0 0.0 丢包率:1%,延迟:10ms9024.5 9586.7 9333.2 11073.2 8670.1 0.0 多链接无限制3485.9 3777.6 41637.5 16657.2 849.1 2386.4 丢包率:1%,延迟:10ms14187.2 9154.8 44190.8 28973.0 11637.8 38549.0
通过统计结果来看,SCS有三项第一,一项第二。特别是没有加入丢包和网络延迟的情况下,性能表现非常好。下一步对它和Thrift进行深入的研究。