Использование канала GRPC одновременно в Net Core 3.0 - PullRequest
2 голосов
/ 18 октября 2019

Согласно документации , клиент 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); 
 });

Или мне нужно создать собственный канал для каждого потока (задачи).

1 Ответ

0 голосов
/ 22 октября 2019

Как заметил @Mike, GrpcChannel использует HttpClient под капотом. Итак, согласно this , мы, вероятно, можем создать одного 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];

        Stopwatch watcher = new Stopwatch();
        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!");
            });
        }

        watcher.Start();
        for (int i = 0; i < threadCount; ++i)
        {
            threads[i].Start(i);
        }

        for (int i = 0; i < threadCount; ++i)
        {
            threads[i].Join();
        }
        watcher.Stop();
        Console.WriteLine($"Elapsed time: {watcher.ElapsedMilliseconds}");

Собственный канал для каждого потока

        string uri = $"https://localhost:5001";

        int threadCount = 6;
        Thread[] threads = new Thread[threadCount];

        Stopwatch watcher = new Stopwatch();
        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);

        watcher.Start();
        for (int i = 0; i < threadCount; ++i)
        {
            threads[i].Start(i);
        }

        for (int i = 0; i < threadCount; ++i)
        {
            threads[i].Join();
        }
        watcher.Stop();
        Console.WriteLine($"Elapsed time: {watcher.ElapsedMilliseconds}");

Я получаю примерно одинаковое время в обоихслучаи без каких-либо ошибок.
Резюме, я могу сделать вывод, что мы можем создать один канал GRPC и повторно использовать его в приложении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...