diff --git a/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs b/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs index 83cae164f..5bef708fd 100644 --- a/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs +++ b/packages/csharp/ArmoniK.Api.Client/Options/GrpcClient.cs @@ -154,5 +154,10 @@ public bool HasClientCertificate /// Password used for proxy authentication /// public string ProxyPassword { get; set; } = ""; + + /// + /// Enable the option SO_REUSE_UNICASTPORT upon socket opening to limit port exhaustion + /// + public bool ReusePorts { get; set; } = true; } } diff --git a/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs b/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs index da3828806..24b7515af 100644 --- a/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs +++ b/packages/csharp/ArmoniK.Api.Client/Submitter/GrpcChannelFactory.cs @@ -274,6 +274,11 @@ private static GrpcChannel CreateChannelInternal(GrpcClient optionsGrpcClient, throw new InvalidOperationException($"{nameof(optionsGrpcClient.Endpoint)} should not be null or empty"); } + if (optionsGrpcClient.ReusePorts) + { + ServicePointManager.ReusePort = true; + } + var serviceConfig = new ServiceConfig { MethodConfigs = @@ -389,6 +394,8 @@ private static GrpcChannel CreateChannelInternal(GrpcClient optionsGrpcClient, proxyType, handlerType, logger); + httpHandler = new Handler(httpHandler, + logger); // Warn that RequestTimeout is not supported. // If required, it could be easily implemented with a DelegatingHandler and a cancellationToken delayed cancellation @@ -625,5 +632,30 @@ private enum HandlerType /// Web, } + + private class Handler : DelegatingHandler + { + private readonly ILogger? logger_; + + internal Handler(HttpMessageHandler inner, + ILogger? logger) + : base(inner) + => logger_ = logger; + + protected override async Task SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) + { + var response = await base.SendAsync(request, + cancellationToken) + .ConfigureAwait(false); + + if (response.Headers.ConnectionClose is true) + { + logger_?.LogInformation("Connection closing has been requested, performance degradation is expected"); + } + + return response; + } + } } }