使用 FieldMask 提高 C# gRpc 服务性能
前言
想象一下,有一個服務提供個多個客戶端調用,但不是所有客戶端都需要全部的返回參數:
比如商品列表服務返回商品的所有信息,而訂單服務調用商品列表服務,但它其實只需要商品的編碼和名稱就夠了。
當然,我們可以為這個需求單獨創建一個服務,但是這樣不太靈活,比如又需要商品的編碼和分類的時候怎么辦?
但是,大而全的服務方法會導致計算和傳輸成本可能很高,如果我們能夠了解響應中哪些字段不需要提供給調用者,從而避免進行不必要的計算和傳輸,這對提高服務性能通常是非常有益的。
在實現 gRPC 服務時,我們可以使用?protobuf FieldMask?實現上述功能。
FieldMask
默認情況下,gRPC 使用 protobuf 作為其接口定義語和數據序列化協議。
FieldMask 是一個 protobuf 消息,包含一個名為 paths 的字段,用于指定用于指定讀取操作返回或更新操作修改的字段:
message?FieldMask?{repeated?string?paths?=?1; }下面,讓我們看一個例子,如何在 C# gRpc 服務中使用它。
Demo
1.定義 .proto 文件
在 .proto 文件中定義服務和消息:
syntax?=?"proto3";option?csharp_namespace?=?"GrpcService2"; import?"google/protobuf/field_mask.proto";package?greet;//?The?greeting?service?definition. service?Greeter?{//?Sends?a?greetingrpc?SayHello?(HelloRequest)?returns?(HelloReply); }//?The?request?message?containing?the?user's?name. message?HelloRequest?{string?name?=?1;google.protobuf.FieldMask?field_mask?=?2; }//?The?response?message?containing?the?greetings. message?HelloReply?{string?message1?=?1;string?message2?=?2;string?message3?=?3;string?message4?=?4;string?message5?=?5; }關鍵點是下面2句:
//?引用 field_mask 消息 import?"google/protobuf/field_mask.proto";//定義請求字段 google.protobuf.FieldMask?field_mask?=?2;2.實現服務端
服務端代碼如下,返回了5個字段:
public?class?GreeterService?:?Greeter.GreeterBase {private?readonly?ILogger<GreeterService>?_logger;public?GreeterService(ILogger<GreeterService>?logger){_logger?=?logger;}public?override?Task<HelloReply>?SayHello(HelloRequest?request,?ServerCallContext?context){var?reply?=?new?HelloReply{Message1?=?"Hello?"?+?request.Name?+?",這是第1條消息",Message2?=?"Hello?"?+?request.Name?+?",這是第2條消息",Message3?=?"Hello?"?+?request.Name?+?",這是第3條消息",Message4?=?"Hello?"?+?request.Name?+?",這是第4條消息",Message5?=?"Hello?"?+?request.Name?+?",這是第5條消息"};return?Task.FromResult(reply);} }3.實現客戶端
客戶端代碼如下:
using?var?channel?=?GrpcChannel.ForAddress("https://localhost:5001"); var?client?=?new?Greeter.GreeterClient(channel);FieldMask?fieldMask?=?new?FieldMask(); fieldMask.Paths.AddRange(new?string[]?{?"message2",?"message4"?});var?request?=?new?HelloRequest?{?Name?=?"My?IO"?}; request.FieldMask?=?fieldMask;var?reply?=?await?client.SayHelloAsync(request);Console.WriteLine($@"Greeting:? {reply.Message1} {reply.Message2} {reply.Message3} {reply.Message4} {reply.Message5} "?);傳入了 FieldMask,這里只需要 message2、message4 字段。
運行程序,發現有問題,還是返回了所有字段:
4.修改服務端
這其實是在服務端沒有判斷 fieldMask,修改服務端代碼:
var?mergedReply?=?new?HelloReply(); request.FieldMask.Merge(reply,?mergedReply);return?Task.FromResult(mergedReply);結論
在本文中,我們看到了如何使用 FieldMask ,這里僅僅是控制不返回字段,你可以自行實現其他邏輯。
想了解更多內容,請關注我的個人公眾號”My IO“
總結
以上是生活随笔為你收集整理的使用 FieldMask 提高 C# gRpc 服务性能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 完美:C# Blazor中显示Markd
- 下一篇: C#中的var理解