測試環境
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實現方式會慢這么多,可能是封裝的代碼還需要優化吧,相信官方在后面的版本會修復這個問題。
2019/11/06更新
我此前在官方倉庫提了個issue,也得到了作者反饋,作者的意思是至少比WebApi快,O(∩_∩)O哈哈~ https://github.com/grpc/grpc-dotnet/issues/628