[英]An using GRPC Channel concurrently in Net Core 3.0
根據文檔,gRPC 客戶端是從通道創建的。 可以從一個通道創建多個具體的 gRPC 客戶端,包括不同類型的客戶端,但我沒有找到任何有關並發的信息。
所以,我的問題是,我可以使用該通道進行如下並發呼叫嗎?
var channel = GrpcChannel.ForAddress("https://localhost:5001");
// the first task
Task.Run(() => {
var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });
Console.WriteLine("Greeting: " + response.Message);
});
// the second task
Task.Run(() => {
var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });
Console.WriteLine("Greeting: " + response.Message);
});
或者我需要為每個線程(任務)創建自己的通道。
正如@Mike 所指出的,GrpcChannel 在后台使用 HttpClient。 因此,根據這個,我們可能可以創建單個 http 客戶端並在應用程序的整個生命周期中重用它。
HttpClient 旨在被實例化一次並在應用程序的整個生命周期中重復使用。
我已經建立了一個簡單的示例來調查該區域。
GRPS服務:
public class GreeterService
: Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
//Server side handler of the SayHello RPC
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
_logger.LogInformation($"Sending hello to {request.Name}");
Thread.Sleep(500);
return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
}
}
所有線程的單一通道
string uri = $"https://localhost:5001";
var channel = GrpcChannel.ForAddress(uri, new GrpcChannelOptions()
{
HttpClient = HttpClientFactory.Create(),
DisposeHttpClient = true
});
int threadCount = 6;
Thread[] threads = new Thread[threadCount];
for(int i = 0; i < threadCount; ++i)
{
threads[i] = new Thread((index) =>
{
Console.WriteLine($"Thread({(int)index}) has been started!");
for (int req = 0; req < 75; ++req)
{
var client = new Greeter.GreeterClient(channel);
client.SayHello(new HelloRequest()
{
Name = $"Thread {(int)index}"
});
}
Console.WriteLine($"Thread({(int)index}) has been finished!");
});
}
for (int i = 0; i < threadCount; ++i)
{
threads[i].Start(i);
}
for (int i = 0; i < threadCount; ++i)
{
threads[i].Join();
}
每個線程都有自己的頻道
string uri = $"https://localhost:5001";
int threadCount = 6;
Thread[] threads = new Thread[threadCount];
for(int i = 0; i < threadCount; ++i)
{
threads[i] = new Thread((index) =>
{
var channel = GrpcChannel.ForAddress(uri, new GrpcChannelOptions()
{
HttpClient = HttpClientFactory.Create(),
DisposeHttpClient = true
});
Console.WriteLine($"Thread({(int)index}) has been started!");
for (int req = 0; req < 75; ++req)
{
var client = new Greeter.GreeterClient(channel);
client.SayHello(new HelloRequest()
{
Name = $"Thread {(int)index}"
});
}
Console.WriteLine($"Thread({(int)index}) has been finished!");
});
}
Thread.Sleep(1000 * 10);
for (int i = 0; i < threadCount; ++i)
{
threads[i].Start(i);
}
for (int i = 0; i < threadCount; ++i)
{
threads[i].Join();
}
總結,我可以得出一個結論,我們可以創建一個單一的 GRPC 通道並在應用程序中重用它。 但我不知道使用一個渠道處理多個請求的效果如何
我看到這個問題得到了回答,但我想補充一點,文檔中有關於客戶端並發的部分。 如果有人新閱讀了這個問題,我希望這會有所幫助。
關於gRPC 性能和實踐的“重用 gRPC 通道”一章。
通道可以安全地在 gRPC 調用之間共享和重用:
- gRPC 客戶端是使用通道創建的。 gRPC 客戶端是輕量級對象,不需要緩存或重用。
- 可以從一個通道創建多個 gRPC 客戶端,包括不同類型的客戶端。
- 一個通道和從通道創建的客戶端可以被多個線程安全地使用。
- 從通道創建的客戶端可以同時進行多個調用。
“連接並發”一章對這個主題也很有幫助。
注意:查看主題配置以配置服務和客戶端通道。
GrpcChannel
表示一個 gRPC 通道。 通道是與遠程服務器的長期連接的抽象。 客戶端對象可以重用相同的通道。 與調用遠程調用相比,創建通道是一項昂貴的操作,因此通常您應該為盡可能多的調用重用單個通道。
沒有關於客戶端並發的細節,但核心概念主題也非常有幫助,讓我們了解 gRPC 在底層是如何工作的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.