用 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 greeting rpc 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 ,這裡僅僅是控制不返回字段,大傢可以自行實現其他邏輯。
到此這篇關於用 FieldMask 提高 C# gRpc 的服務性能的文章就介紹到這瞭,更多相關用 FieldMask 提高 C# gRpc 的服務性能內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Go gRPC環境安裝教程示例詳解
- 如何在.NET Core中為gRPC服務設計消息文件(Proto)
- 如何用Python搭建gRPC服務
- 使用C# 11的靜態接口方法改進 面向約定 的設計方法
- 基於微服務框架go-micro開發gRPC應用程序