日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

用?FieldMask?提高?C#?gRpc?的服務性能_C#教程

作者:My?IO ? 更新時間: 2022-05-03 編程語言

前言:

想象一下,有一個服務提供個多個客戶端調用,但不是所有客戶端都需要全部的返回參數:

?比如商品列表服務返回商品的所有信息,而訂單服務調用商品列表服務,但它其實只需要商品的編碼和名稱就夠了。?

當然,我們可以為這個需求單獨創建一個服務,但是這樣不太靈活,比如又需要商品的編碼和分類的時候怎么辦?

但是,大而全的服務方法會導致計算和傳輸成本可能很高,如果我們能夠了解響應中哪些字段不需要提供給調用者,從而避免進行不必要的計算和傳輸,這對提高服務性能通常是非常有益的。

在實現 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 _logger;
? ? public GreeterService(ILogger logger)
? ? {
? ? ? ? _logger = logger;
? ? }

? ? public override Task 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,這里只需要 message2message4 字段。

運行程序,發現有問題,還是返回了所有字段:

?4.修改服務端?

這其實是在服務端沒有判斷 fieldMask,修改服務端代碼:

var mergedReply = new HelloReply();
request.FieldMask.Merge(reply, mergedReply);

return Task.FromResult(mergedReply);

結論:

在本文中,我們看到了如何使用 FieldMask ,這里僅僅是控制不返回字段,大家可以自行實現其他邏輯。

原文鏈接:https://blog.51cto.com/MyIO/5063206

欄目分類
最近更新