测试环境

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实现方式会慢这么多,可能是封装的代码还需要优化吧,相信官方在后面的版本会修复这个问题。