测试环境
gRPC & WebApi 服务运行环境
项目 | 值 |
CPU | 1 |
内存 | 2GB |
操作系统 | ubuntu 虚拟机 |
软件 | docker |
运行时 | .NET Core 3.0 |
测试场景
使用不同gRPC和WebApi实现一个UserService,提供SayHi的接口,接收一个字符串参数,返回对这个字符串的简单拼接后的结果,进行单连接/多连接循环调用、并行调用,记录最小耗时、最大耗时、平均耗时。
我非常认同内存、CPU占用很重要,但水平有限,这里不做测试了,起初设计的是采用微软官方推荐的方式实现gRPC服务,但这种方式实测下来比WebApi还慢,因此增加了采用gRPC官方提供的实现方式进行对比。
gRPC官方提供的实现方式: https://github.com/grpc/grpc/tree/master/src/csharp
.netcore3.0推荐的实现方式是用VS2019创建gRPC项目时直接使用gRPC模版创建,这种情况下实际创建的是一个Web项目,并且自动引用了Grpc.AspNetCore包,这个包里面做了一些封装且引用了Google.Protobuf、Grpc.Tools、Grpc.Core.Api等
最终的测试项目结构如下
- GrpcService:基于.netcore3.0推荐的gRPC实现方式,实际是一个Web项目
- GrpcServiceConsoleApp:基于gRPC官方提供的实现方式,是一个控制台应用程序
- WebApi:基于.netcore3.0的WebApi项目
- Test:用于测试调用的客户端,是一个控制台应用程序
测试代码在此: https://github.com/RiccoYuan/gRPC.NetCoreTest
测试结果
1000次For循环调用,循环里面每次创建新的连接
项目/耗时(毫秒) | 平均耗时 | 最小耗时 | 最大耗时 |
GrpcService | 13.113 | 9 | 738 |
GrpcServiceConsoleApp | 2.854 | 1 | 176 |
WebApi | 6.331 | 5 | 56 |
1000次For循环调用,只在循环外面创建一次连接
项目/耗时(毫秒) | 平均耗时 | 最小耗时 | 最大耗时 |
GrpcService | 5.649 | 4 | 18 |
GrpcServiceConsoleApp | 2.178 | 1 | 131 |
WebApi | 1.155 | 1 | 7 |
1000次Parallel并行调用,这里只测试了每次创建新的连接的情况
项目/耗时(毫秒) | 平均耗时 | 最小耗时 | 最大耗时 |
GrpcService | 13296.676 | 10875 | 17642 |
GrpcServiceConsoleApp | 2350.708 | 471 | 3652 |
WebApi | 8128.383 | 943 | 10645 |
手动进行了多次测试,结果相对而言都差不多,得出以下结论:
- 从客户端建立连接到拿到请求响应,在单线程循环调用和多线程并行调用,gRPC的耗时都比WebApi快3倍左右,符合预期。
- 在客户端只建立单个连接的情况下,WebApi比gRPC更快,这里面的原因我还不知道。
- 上述的任何场景下,gRPC官方提供的实现方式比.netcore3.0推荐的gRPC实现方式快。
暂且认为,gRPC官方提供的实现方式
优于WebApi
优于.netcore3.0推荐的gRPC实现方式
为什么.netcore3.0推荐的gRPC实现方式会慢这么多,可能是封装的代码还需要优化吧,相信官方在后面的版本会修复这个问题。