繁体   English   中英

在 Net Core 3.0 中同时使用 GRPC 通道

[英]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 通道并在应用程序中重用它。 但我不知道使用一个渠道处理多个请求的效果如何

我看到这个问题得到了回答,但我想补充一点,文档中有关于客户端并发的部分。 如果有人新阅读了这个问题,我希望这会有所帮助。

微软文档

.NET Core 上的 gRPC 介绍

关于gRPC 性能和实践的“重用 gRPC 通道”一章。

通道可以安全地在 gRPC 调用之间共享和重用:

  • gRPC 客户端是使用通道创建的。 gRPC 客户端是轻量级对象,不需要缓存或重用。
  • 可以从一个通道创建多个 gRPC 客户端,包括不同类型的客户端。
  • 一个通道和从通道创建的客户端可以被多个线程安全地使用。
  • 从通道创建的客户端可以同时进行多个调用。

连接并发”一章对这个主题也很有帮助。

注意:查看主题配置以配置服务和客户端通道。

gRPC API 文档

命名空间 Grpc.Net.Client

GrpcChannel

表示一个 gRPC 通道。 通道是与远程服务器的长期连接的抽象。 客户端对象可以重用相同的通道。 与调用远程调用相比,创建通道是一项昂贵的操作,因此通常您应该为尽可能多的调用重用单个通道。

gRPC 文档

没有关于客户端并发的细节,但核心概念主题也非常有帮助,让我们了解 gRPC 在底层是如何工作的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM