From 8b6ecf3a7ee846384c2888e56904260a61b666fe Mon Sep 17 00:00:00 2001 From: anitarua Date: Mon, 4 Mar 2024 16:08:30 -0800 Subject: [PATCH 1/3] fix: disable keepalive for control clients --- src/Momento.Sdk/Internal/GrpcManager.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Momento.Sdk/Internal/GrpcManager.cs b/src/Momento.Sdk/Internal/GrpcManager.cs index da5ee315..c25e4aee 100644 --- a/src/Momento.Sdk/Internal/GrpcManager.cs +++ b/src/Momento.Sdk/Internal/GrpcManager.cs @@ -69,13 +69,24 @@ internal GrpcManager(IGrpcConfiguration grpcConfig, ILoggerFactory loggerFactory #if NET5_0_OR_GREATER if (SocketsHttpHandler.IsSupported) // see: https://github.com/grpc/grpc-dotnet/blob/098dca892a3949ade411c3f2f66003f7b330dfd2/src/Shared/HttpHandlerFactory.cs#L28-L30 { + var keepAliveWithoutCallsPolicy = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePermitWithoutCalls == true ? System.Net.Http.HttpKeepAlivePingPolicy.Always : System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests; + var keepAliveTimeout = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingTimeout; + var keepAlivePingDelay = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingDelay; + + // Disable keepalives for control clients and convert KeepAlivePermitWithoutCalls from bool to HttpKeepAlivePingPolicy + if (loggerName.Contains("Control")) { + keepAliveWithoutCallsPolicy = System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests; + keepAliveTimeout = System.Threading.Timeout.InfiniteTimeSpan; + keepAlivePingDelay = System.Threading.Timeout.InfiniteTimeSpan; + } + channelOptions.HttpHandler = new SocketsHttpHandler { EnableMultipleHttp2Connections = grpcConfig.SocketsHttpHandlerOptions.EnableMultipleHttp2Connections, PooledConnectionIdleTimeout = grpcConfig.SocketsHttpHandlerOptions.PooledConnectionIdleTimeout, - KeepAlivePingTimeout = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingTimeout, - KeepAlivePingDelay = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingDelay, - KeepAlivePingPolicy = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePermitWithoutCalls == true ? System.Net.Http.HttpKeepAlivePingPolicy.Always : System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests, + KeepAlivePingTimeout = keepAliveTimeout, + KeepAlivePingDelay = keepAlivePingDelay, + KeepAlivePingPolicy = keepAliveWithoutCallsPolicy, }; } #elif USE_GRPC_WEB From 456c4fb01ff91a92e088751a50ce9aafc139fc95 Mon Sep 17 00:00:00 2001 From: anitarua Date: Tue, 5 Mar 2024 09:33:11 -0800 Subject: [PATCH 2/3] more idiomatic way to override control clients keepalive settings --- .../Transport/IVectorIndexTransportStrategy.cs | 7 +++++++ .../StaticVectorIndexTransportStrategy.cs | 5 +++++ src/Momento.Sdk/Internal/GrpcManager.cs | 17 +++-------------- src/Momento.Sdk/Internal/ScsControlClient.cs | 13 ++++++++++++- .../Internal/VectorIndexControlClient.cs | 13 ++++++++++++- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/Momento.Sdk/Config/Transport/IVectorIndexTransportStrategy.cs b/src/Momento.Sdk/Config/Transport/IVectorIndexTransportStrategy.cs index 78935d4e..ebaa158a 100644 --- a/src/Momento.Sdk/Config/Transport/IVectorIndexTransportStrategy.cs +++ b/src/Momento.Sdk/Config/Transport/IVectorIndexTransportStrategy.cs @@ -26,4 +26,11 @@ public interface IVectorIndexTransportStrategy /// /// A new IVectorIndexTransportStrategy with the specified client timeout public IVectorIndexTransportStrategy WithClientTimeout(TimeSpan clientTimeout); + + /// + /// Copy constructor to update the SocketsHttpHandler's options + /// + /// + /// + public IVectorIndexTransportStrategy WithSocketsHttpHandlerOptions(SocketsHttpHandlerOptions options); } diff --git a/src/Momento.Sdk/Config/Transport/StaticVectorIndexTransportStrategy.cs b/src/Momento.Sdk/Config/Transport/StaticVectorIndexTransportStrategy.cs index 90617168..46a708b3 100644 --- a/src/Momento.Sdk/Config/Transport/StaticVectorIndexTransportStrategy.cs +++ b/src/Momento.Sdk/Config/Transport/StaticVectorIndexTransportStrategy.cs @@ -37,6 +37,11 @@ public IVectorIndexTransportStrategy WithClientTimeout(TimeSpan clientTimeout) return new StaticVectorIndexTransportStrategy(_loggerFactory, GrpcConfig.WithDeadline(clientTimeout)); } + public IVectorIndexTransportStrategy WithSocketsHttpHandlerOptions(SocketsHttpHandlerOptions options) + { + return new StaticVectorIndexTransportStrategy(_loggerFactory, GrpcConfig.WithSocketsHttpHandlerOptions(options)); + } + /// /// Test equality by value. /// diff --git a/src/Momento.Sdk/Internal/GrpcManager.cs b/src/Momento.Sdk/Internal/GrpcManager.cs index c25e4aee..da5ee315 100644 --- a/src/Momento.Sdk/Internal/GrpcManager.cs +++ b/src/Momento.Sdk/Internal/GrpcManager.cs @@ -69,24 +69,13 @@ internal GrpcManager(IGrpcConfiguration grpcConfig, ILoggerFactory loggerFactory #if NET5_0_OR_GREATER if (SocketsHttpHandler.IsSupported) // see: https://github.com/grpc/grpc-dotnet/blob/098dca892a3949ade411c3f2f66003f7b330dfd2/src/Shared/HttpHandlerFactory.cs#L28-L30 { - var keepAliveWithoutCallsPolicy = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePermitWithoutCalls == true ? System.Net.Http.HttpKeepAlivePingPolicy.Always : System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests; - var keepAliveTimeout = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingTimeout; - var keepAlivePingDelay = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingDelay; - - // Disable keepalives for control clients and convert KeepAlivePermitWithoutCalls from bool to HttpKeepAlivePingPolicy - if (loggerName.Contains("Control")) { - keepAliveWithoutCallsPolicy = System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests; - keepAliveTimeout = System.Threading.Timeout.InfiniteTimeSpan; - keepAlivePingDelay = System.Threading.Timeout.InfiniteTimeSpan; - } - channelOptions.HttpHandler = new SocketsHttpHandler { EnableMultipleHttp2Connections = grpcConfig.SocketsHttpHandlerOptions.EnableMultipleHttp2Connections, PooledConnectionIdleTimeout = grpcConfig.SocketsHttpHandlerOptions.PooledConnectionIdleTimeout, - KeepAlivePingTimeout = keepAliveTimeout, - KeepAlivePingDelay = keepAlivePingDelay, - KeepAlivePingPolicy = keepAliveWithoutCallsPolicy, + KeepAlivePingTimeout = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingTimeout, + KeepAlivePingDelay = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingDelay, + KeepAlivePingPolicy = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePermitWithoutCalls == true ? System.Net.Http.HttpKeepAlivePingPolicy.Always : System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests, }; } #elif USE_GRPC_WEB diff --git a/src/Momento.Sdk/Internal/ScsControlClient.cs b/src/Momento.Sdk/Internal/ScsControlClient.cs index 9ec7e952..e348ccc2 100644 --- a/src/Momento.Sdk/Internal/ScsControlClient.cs +++ b/src/Momento.Sdk/Internal/ScsControlClient.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging; using Momento.Protos.ControlClient; using Momento.Sdk.Config; +using Momento.Sdk.Config.Transport; using Momento.Sdk.Exceptions; using Momento.Sdk.Responses; @@ -20,7 +21,17 @@ internal sealed class ScsControlClient : IDisposable public ScsControlClient(IConfiguration config, string authToken, string endpoint) { - this.grpcManager = new ControlGrpcManager(config, authToken, endpoint); + // Override the sockets http handler options to disable keepalive + var overrideKeepalive = SocketsHttpHandlerOptions.Of( + pooledConnectionIdleTimeout: config.TransportStrategy.GrpcConfig.SocketsHttpHandlerOptions.PooledConnectionIdleTimeout, + enableMultipleHttp2Connections: config.TransportStrategy.GrpcConfig.SocketsHttpHandlerOptions.EnableMultipleHttp2Connections, + keepAlivePingTimeout: System.Threading.Timeout.InfiniteTimeSpan, + keepAlivePingDelay: System.Threading.Timeout.InfiniteTimeSpan, + keepAlivePermitWithoutCalls: false + ); + var controlConfig = config.WithTransportStrategy(config.TransportStrategy.WithSocketsHttpHandlerOptions(overrideKeepalive)); + + this.grpcManager = new ControlGrpcManager(controlConfig, authToken, endpoint); this.authToken = authToken; this._logger = config.LoggerFactory.CreateLogger(); this._exceptionMapper = new CacheExceptionMapper(config.LoggerFactory); diff --git a/src/Momento.Sdk/Internal/VectorIndexControlClient.cs b/src/Momento.Sdk/Internal/VectorIndexControlClient.cs index 8f5a9791..2f77553d 100644 --- a/src/Momento.Sdk/Internal/VectorIndexControlClient.cs +++ b/src/Momento.Sdk/Internal/VectorIndexControlClient.cs @@ -9,6 +9,7 @@ using Momento.Sdk.Requests.Vector; using Momento.Sdk.Responses.Vector; using Momento.Sdk.Config; +using Momento.Sdk.Config.Transport; namespace Momento.Sdk.Internal; @@ -22,7 +23,17 @@ internal sealed class VectorIndexControlClient : IDisposable public VectorIndexControlClient(IVectorIndexConfiguration config, string authToken, string endpoint) { - grpcManager = new VectorIndexControlGrpcManager(config, authToken, endpoint); + // Override the sockets http handler options to disable keepalive + var overrideKeepalive = SocketsHttpHandlerOptions.Of( + pooledConnectionIdleTimeout: config.TransportStrategy.GrpcConfig.SocketsHttpHandlerOptions.PooledConnectionIdleTimeout, + enableMultipleHttp2Connections: config.TransportStrategy.GrpcConfig.SocketsHttpHandlerOptions.EnableMultipleHttp2Connections, + keepAlivePingTimeout: System.Threading.Timeout.InfiniteTimeSpan, + keepAlivePingDelay: System.Threading.Timeout.InfiniteTimeSpan, + keepAlivePermitWithoutCalls: false + ); + var controlConfig = config.WithTransportStrategy(config.TransportStrategy.WithSocketsHttpHandlerOptions(overrideKeepalive)); + + grpcManager = new VectorIndexControlGrpcManager(controlConfig, authToken, endpoint); _logger = config.LoggerFactory.CreateLogger(); _exceptionMapper = new CacheExceptionMapper(config.LoggerFactory); } From 59a0efacbe2e25bd0830c08f3c4a4781ff9949f9 Mon Sep 17 00:00:00 2001 From: anitarua Date: Tue, 5 Mar 2024 11:28:49 -0800 Subject: [PATCH 3/3] remove redundant ==true --- src/Momento.Sdk/Internal/GrpcManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Momento.Sdk/Internal/GrpcManager.cs b/src/Momento.Sdk/Internal/GrpcManager.cs index da5ee315..f129dd27 100644 --- a/src/Momento.Sdk/Internal/GrpcManager.cs +++ b/src/Momento.Sdk/Internal/GrpcManager.cs @@ -75,7 +75,7 @@ internal GrpcManager(IGrpcConfiguration grpcConfig, ILoggerFactory loggerFactory PooledConnectionIdleTimeout = grpcConfig.SocketsHttpHandlerOptions.PooledConnectionIdleTimeout, KeepAlivePingTimeout = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingTimeout, KeepAlivePingDelay = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePingDelay, - KeepAlivePingPolicy = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePermitWithoutCalls == true ? System.Net.Http.HttpKeepAlivePingPolicy.Always : System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests, + KeepAlivePingPolicy = grpcConfig.SocketsHttpHandlerOptions.KeepAlivePermitWithoutCalls ? System.Net.Http.HttpKeepAlivePingPolicy.Always : System.Net.Http.HttpKeepAlivePingPolicy.WithActiveRequests, }; } #elif USE_GRPC_WEB