本篇文章写于2022年02月26日,从公众号|掘金|CSDN手工同步过来(博客搬家),本篇为原创文章。
公司内部的RPC框架,经过长时间的发展,已经由完全自研演进到底层替换为Dubbo实现,但使用方式(API)还是不变。
由于使用了PB序列化协议,以及业务码+操作码定义接口的方式,非常的影响开发效率,可理解差,链路排查困难等问题,不断被业务方吐槽。因此就有了第三个版本,继续基于Dubbo扩展点,设计开发提供接近Dubbo原生的使用方式。
由于原生提供的Http rpc协议的实现,不仅使用了Spring框架的API,还使用了Java的原生序列化,所以我们基于扩展点自实现了Http rpc协议,移除对Spring的强依赖,并使用json序列化协议。
此次性能测试对比的是我们基于Dubbo扩展点自实现的Http rpc协议,与Dubbo原生Dubbo rpc协议的单次请求响应平均耗时、吞吐量。
- Dubbo rpc:Dubbo rpc协议 + hessian2序列化协议
- Http rpc:Http rpc协议(服务端使用jetty,客户端使用netty) + json序列化协议(使用fastjson)
基准测试目的
- 在最初设计评审时,关于是采用http协议还是dubbo协议,我们对这两者在性能方面的影响还存在疑虑。
- 有Dubbo rpc的性能数据做对比,对自实现的Http rpc,性能应该优化到多少才算最优,心里有个底。
基准测试接口
接口实现不做任何业务处理,排除业务耗时对基准测试的影响。
RPC接口定义:
public interface DemoeService {
Result<String> sayHello(String name);
}
提供者实现:
@ServiceProvider
public class DemoeServiceImpl implements DemoeService {
@Override
public Result<String> sayHello(String name) {
Result<String> result = new Result<>(0, name);
return result;
}
}
基准测试说明
一、以相同配置,不同rpc协议实现注册DemoService服务提供者。
服务提供者参数配置如下: * 工作线程数:200 (处理业务) * IO线程数:4 (处理数据包的读写、编解码)
二、以相同配置,不同rpc协议创建DemoService服务消费者。
唯一的区别是,使用http rpc协议需要配置连接池,使用dubbo rpc协议只配置单一长连接。
使用http rpc协议,服务消费者连接池配置: * 最大连接数:无最大连接数限制; * 最大空闲连接数:1024;
三、使用open-jdk官方开源的JMH基准测试工具对DemoService接口分别进行平均耗时测量、吞吐量测量。
环境
- 本地测试,MacBook Pro 8核16G
- 尽量关闭多余进程
- 先启动dubbo协议服务提供者和消费者,测完dubbo协议后,再测http协议
- dubbo版本:2.6.4 (二次开发过,增加了一些功能特性)
基准测试结果
Http rpc与Dubbo rpc基准测试: * 测量指标:平均耗时、吞吐量 * 预热1次,每次5秒钟 * 测量5次,每次5秒钟 * 消费者线程数200(模拟并发) * 数据包足够小(调用的接口信息+参数,数据包小于1KB)
初次测试
Http rpc测量结果:
Benchmark Mode Cnt Score Error Units
HttpConsumerBenchmarkTest.testHttp thrpt 5 1.408 ± 0.235 ops/ms
HttpConsumerBenchmarkTest.testHttp avgt 5 233.966 ± 163.614 ms/op
Dubbo rpc测量结果:
Benchmark Mode Cnt Score Error Units
DubboConsumerBenchmarkTest.testDubbo thrpt 5 42.829 ± 24.597 ops/ms
DubboConsumerBenchmarkTest.testDubbo avgt 5 4.739 ± 0.192 ms/op
测量结果对比 | | 吞吐量 | 平均耗时 | | ——— | ——– | ——— | | http rpc | 1408ops | 233.966ms | | dubbo rpc | 42829ops | 4.739ms |
此次测试结果数据差别有些大,初步定位耗时在服务端。
经关键步骤打印日记后发现,数据序列化和反序列化耗时比较严重。
经验证后,发现fastjson序列化和反序列化泛型非常耗时,并且改用gson后耗时降低,性能数据表现接近Dubbo rpc。
优化后重新测试
HTTP rpc(使用json + gson)
Benchmark Mode Cnt Score Error Units
HttpConsumerBenchmarkTest.testHttp thrpt 5 31.550 ± 6.477 ops/ms
HttpConsumerBenchmarkTest.testHttp avgt 5 6.487 ± 1.512 ms/op
Dubbo rpc(使用hessian2)
Benchmark Mode Cnt Score Error Units
DubboConsumerBenchmarkTest.testDubbo thrpt 5 42.829 ± 24.597 ops/ms
DubboConsumerBenchmarkTest.testDubbo avgt 5 4.739 ± 0.192 ms/op
考虑到序列化协议也是影响性能的重要因素,因此我们增加了Dubbo rpc使用json序列化协议的基准测试。
Dubbo(序列化使用fastjson)
Benchmark Mode Cnt Score Error Units
DubboConsumerBenchmarkTest.testDubbo thrpt 5 21.416 ± 7.571 ops/ms
DubboConsumerBenchmarkTest.testDubbo avgt 5 9.687 ± 2.329 ms/op
Dubbo(序列化使用gson)
Benchmark Mode Cnt Score Error Units
DubboConsumerBenchmarkTest.testDubbo thrpt 5 24.460 ± 7.396 ops/ms
DubboConsumerBenchmarkTest.testDubbo avgt 5 7.743 ± 1.256 ms/op
可以看到,同样使用json序列化协议,且使用gson工具,Http rpc与Dubbo rpc性能相差在0.5~1ms之间,并且Http rpc的耗时略低,吞吐量更高;Dubbo rpc同样使用json序列化协议,使用gson工具与fastjson工具性能相差2ms左右,fastjson性能表现较差。
此测试数据仅供参考!
官方性能压测报告:性能测试报告