近期开始研究分布式架构,会涉及到一个最核心的组件: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,局域网环境) Thrift Thrift(Teld) gRPC Halibut SCS Shuttler.net 单链接 无限制 3651.0 3774.8 3963.5 908.0 736.0 0.0 丢包率:1%,延迟:10ms 9024.5 9586.7 9333.2 11073.2 8670.1 0.0 多链接 无限制 3485.9 3777.6 41637.5 16657.2 849.1 2386.4 丢包率:1%,延迟:10ms 14187.2 9154.8 44190.8 28973.0 11637.8 38549.0
通过统计结果来看,SCS有三项第一,一项第二。特别是没有加入丢包和网络延迟的情况下,性能表现非常好。下一步对它和Thrift进行深入的研究。