[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