cyanfish / grpc-dotnet-namedpipes

Named pipe transport for gRPC in C#/.NET
Apache License 2.0
183 stars 47 forks source link

Increasing the number of parallel requests results in the error “could not connect to all addresses.” #57

Closed SeminDM closed 6 months ago

SeminDM commented 6 months ago

Hello! I have a problem when the number of parallel requests increases.

var channel = new NamedPipeChannel(".", "MY_PIPE", new NamedPipeChannelOptions { ConnectionTimeout = 1000 });
var client = new OperationService.OperationServiceClient(channel);

for (var i = 0; i < 95; i++)
{
    Task.Run(() =>
    {
        while (true)
        {
            try
            {
                client.OperationStart(new OperationStartRequest { OperationName = $"Hello {DateTime.Now.Second}"});
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
    });
}

Such code produces the exception:

Grpc.Core.RpcException: Status(StatusCode="Unavailable", Detail="failed to connect to all addresses")
   at GrpcDotNetNamedPipes.NamedPipeChannel.CreateConnectionContext[TRequest,TResponse](Method`2 method, CallOptions callOptions, TRequest request)
   at GrpcDotNetNamedPipes.NamedPipeChannel.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions callOptions, TRequest request)
   at Grpc.Core.Interceptors.InterceptingCallInvoker.<BlockingUnaryCall>b__3_0[TRequest,TResponse](TRequest req, ClientInterceptorContext`2 ctx)
   at Grpc.Core.ClientBase.ClientBaseConfiguration.ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,TResponse](TRequest request, ClientInterceptorContext`2 context, BlockingUnaryCallContinuation`2 continuation)
   at Grpc.Core.Interceptors.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request)
   at OperationServiceSpace.OperationService.OperationServiceClient.OperationStart(OperationStartRequest request, CallOptions options) in C:\repos\NamedPipesPerfTests\NamedPipesPerfTests\obj\Debug\net7.0\ProfilerGrpc.cs:line 102
   at OperationServiceSpace.OperationService.OperationServiceClient.OperationStart(OperationStartRequest request, Metadata headers, Nullable`1 deadline, CancellationToken cancellationToken) in C:\repos\NamedPipesPerfTests\NamedPipesPerfTests\obj\Debug\net7.0\ProfilerGrpc.cs:line 97
   at Program.<>c__DisplayClass0_0.<<Main>$>b__0() in C:\repos\NamedPipesPerfTests\NamedPipesPerfTests\Program.cs:line 15

Is there the limit for concurrent connections or something similar? Could you please help to workaround this problem?

cyanfish commented 6 months ago

Thanks for the reproducible example, I think this should be fixed in version 3.0.0. I would also recommend using async calls to avoid potential threadpool starvation, e.g.

Task.Run(async () =>
{
    await client.OperationStartAsync(new OperationStartRequest { OperationName = $"Hello {DateTime.Now.Second}"});
});