[C#]gRPC Client連線建立耗時過長經驗分享

[C#]gRPC Client連線建立耗時過長經驗分享

目前主要都在開發gRPC Server端程式, Client端的呼叫大致上僅在Server版更的時候使用簡單的sample測試request送出去之後能得到預期的response,

如果發生錯誤都是不以為意的可能當下網路不通,所以連線失敗…….

近期Client端同事碰上了一個怪異的狀況, 因為避免Server端忙碌而造成Client無限等待, 所以設置了CancellationToken  當呼叫超過5秒沒有得到回應視為Server忙碌擲, 然後擲出超時錯誤

Client端對Domain B會偶發性的在第一次呼叫的時候擲出超時錯誤, 接著在同一條連線執行功能呼叫則都能快速地接收到回應, 但在Domain A則沒有這樣的狀況

我們所使用的plugin 是Grpc.Core  , 程式碼片段如下

var channel = new Channel("target", new SslCredentials("rootCertificates"));
var invoker = new DefaultCallInvoker(channel);
MySVC.MySVCClient client = new MySVC.MySVCClient(invoker);
ProtobufMsg msg = new ProtobufMsg();
using (var ctx = new CancellationTokenSource())
{
	client.QryHeartbeat(msg, null, null, ctx.Token);
}

它是透過Cannel來設定連線物件,  再由Invoker來啟動rpc,

透過debug model進行測試發現出現超時的狀況都是在 新建立的Channel, 此時ChannelState 為Idle

啟動rpc時會就自動建立連接並執行功能呼叫, 起初判斷應該是連線未建立完成就啟動了rpc所擲出的錯誤,

所以調整了程式變成new出Channel後先將連線建立並確認ChannelState為Ready才讓程式繼續往下執行, 

但這時發現ChannelState從Idel → Connecting→ Ready 時間會落在7~10秒, 使用TCPView與Wireshark查看得到下2張圖

後來將資訊提供給同事幫忙查得可以透過環境變數GRPC_DNS_RESOLVER 來指定gRPC要使用的DNS解析器後問題排除:

Environment.SetEnvironmentVariable("GRPC_DNS_RESOLVER", "native");

GRPC_DNS_RESOLVER 聲明要使用的 DNS 解析器。

如果 gRPC 是使用 c-ares 支持構建的,則默認為 ares。否則,將忽略此環境變量的值。

可用的 DNS 解析器包括:

ares(除 iOS、Android 或 Node 之外的大多數平台上的默認設置)- 基於 c-ares 庫的 DNS 解析器 

native - 基於 getaddrinfo() 的 DNS 解析器,創建一個新線程來執行名稱解析

ref:

https://github.com/grpc/grpc/blob/master/doc/environment_variables.md

https://grpc.github.io/grpc/csharp/api/Grpc.Core.html

https://github.com/grpc/grpc/issues/19954

http://lirobo.blogspot.com/2014/04/getaddrinfo.html

 

egan2608@gmail.com