[英]An using GRPC Channel concurrently in Net Core 3.0
According the documentation , a gRPC client is created from a channel.根据文档,gRPC 客户端是从通道创建的。 Multiple concrete gRPC clients can be created from a channel, including different types of clients, but I didn't find any information about concurrency.
可以从一个通道创建多个具体的 gRPC 客户端,包括不同类型的客户端,但我没有找到任何有关并发的信息。
So, my question, Can I use the channel for concurrent calls like below?所以,我的问题是,我可以使用该通道进行如下并发呼叫吗?
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);
});
Or I need to create own channel for each thread(task).或者我需要为每个线程(任务)创建自己的通道。
As @Mike has noted, The GrpcChannel is using HttpClient under the hood.正如@Mike 所指出的,GrpcChannel 在后台使用 HttpClient。 So, according this , we probably can create a single http client and reuse it throughout the life of an application.
因此,根据这个,我们可能可以创建单个 http 客户端并在应用程序的整个生命周期中重用它。
HttpClient is intended to be instantiated once and re-used throughout the life of an application.
HttpClient 旨在被实例化一次并在应用程序的整个生命周期中重复使用。
I have built a simple example to investigate the area.我已经建立了一个简单的示例来调查该区域。
GRPS service: 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 });
}
}
The single channel for all threads所有线程的单一通道
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();
}
Own channel for each thread每个线程都有自己的频道
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();
}
Summary, I can make a conclusion that we can create a single GRPC channel and reuse it in the app.总结,我可以得出一个结论,我们可以创建一个单一的 GRPC 通道并在应用程序中重用它。 But I don't know how effective using one channel for many request is
但我不知道使用一个渠道处理多个请求的效果如何
i see that the question is answered but I wanted to add that there are sections in docs about client concurrency.我看到这个问题得到了回答,但我想补充一点,文档中有关于客户端并发的部分。 If someone new read this question i hope this will be helpful.
如果有人新阅读了这个问题,我希望这会有所帮助。
Introduction to gRPC on .NET Core .NET Core 上的 gRPC 介绍
Chapter " Reuse gRPC channels " on gRPC - Performance and practices .关于gRPC 性能和实践的“重用 gRPC 通道”一章。
Channels are safe to share and reuse between gRPC calls:
通道可以安全地在 gRPC 调用之间共享和重用:
- gRPC clients are created with channels.
gRPC 客户端是使用通道创建的。 gRPC clients are lightweight objects and don't need to be cached or reused.
gRPC 客户端是轻量级对象,不需要缓存或重用。
- Multiple gRPC clients can be created from a channel, including different types of clients.
可以从一个通道创建多个 gRPC 客户端,包括不同类型的客户端。
- A channel and clients created from the channel can safely be used by multiple threads.
一个通道和从通道创建的客户端可以被多个线程安全地使用。
- Clients created from the channel can make multiple simultaneous calls.
从通道创建的客户端可以同时进行多个调用。
" Connection concurrency " chapter on this topic is also very helpful. “连接并发”一章对这个主题也很有帮助。
NOTE: Look topic Configuration for configuring services and client channels.注意:查看主题配置以配置服务和客户端通道。
Namespace Grpc.Net.Client 命名空间 Grpc.Net.Client
GrpcChannel GrpcChannel
Represents a gRPC channel.
表示一个 gRPC 通道。 Channels are an abstraction of long-lived connections to remote servers.
通道是与远程服务器的长期连接的抽象。 Client objects can reuse the same channel.
客户端对象可以重用相同的通道。 Creating a channel is an expensive operation compared to invoking a remote call so in general you should reuse a single channel for as many calls as possible.
与调用远程调用相比,创建通道是一项昂贵的操作,因此通常您应该为尽可能多的调用重用单个通道。
There are no specifics about client concurrency, but Core concepts topic is also very helpful by giving glimpses on how gRPC works underhood.没有关于客户端并发的细节,但核心概念主题也非常有帮助,让我们了解 gRPC 在底层是如何工作的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.