Skip to content

Commit 2116d1e

Browse files
authored
Configure pooled connection lifetime in client factory (#1862)
1 parent 7bfd8e3 commit 2116d1e

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

src/Grpc.Net.ClientFactory/GrpcClientServiceExtensions.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,23 @@ private static IHttpClientBuilder AddGrpcHttpClient<
334334

335335
services.PostConfigure<HttpClientFactoryOptions>(name, options =>
336336
{
337-
options.HttpMessageHandlerBuilderActions.Add(static builder =>
337+
options.HttpMessageHandlerBuilderActions.Add(builder =>
338338
{
339339
if (builder.PrimaryHandler == null)
340340
{
341341
// This will throw in .NET Standard 2.0 with a prompt that a user must set a handler.
342342
// Because it throws it should only be called in PostConfigure if no handler has been set.
343343
var handler = HttpHandlerFactory.CreatePrimaryHandler();
344+
#if NET5_0_OR_GREATER
345+
if (handler is SocketsHttpHandler socketsHttpHandler)
346+
{
347+
// A channel is created once per client, lives forever, and the primary handler never changes.
348+
// It's possible that long lived connections cause the client to miss out on DNS changes.
349+
// Replicate the core benefit of a handler lifetime (periodic connection recreation)
350+
// by setting PooledConnectionLifetime to handler lifetime.
351+
socketsHttpHandler.PooledConnectionLifetime = options.HandlerLifetime;
352+
}
353+
#endif
344354
#if NET5_0
345355
handler = HttpHandlerFactory.EnsureTelemetryHandler(handler);
346356
#endif

test/Grpc.Net.ClientFactory.Tests/DefaultGrpcClientFactoryTests.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ public void CreateClient_NoPrimaryHandlerNet5OrLater_SocketsHttpHandlerConfigure
195195
// Arrange
196196
var services = new ServiceCollection();
197197
services
198-
.AddGrpcClient<TestGreeterClient>(o => o.Address = new Uri("https://localhost"));
198+
.AddGrpcClient<TestGreeterClient>(o => o.Address = new Uri("https://localhost"))
199+
.SetHandlerLifetime(TimeSpan.FromSeconds(10));
199200

200201
var serviceProvider = services.BuildServiceProvider(validateScopes: true);
201202

@@ -206,20 +207,22 @@ public void CreateClient_NoPrimaryHandlerNet5OrLater_SocketsHttpHandlerConfigure
206207
var handler = handlerFactory.CreateHandler(nameof(TestGreeterClient));
207208

208209
// Assert
209-
var hasSocketsHttpHandler = false;
210+
SocketsHttpHandler? socketsHttpHandler = null;
210211
HttpMessageHandler? currentHandler = handler;
211212
while (currentHandler is DelegatingHandler delegatingHandler)
212213
{
213214
currentHandler = delegatingHandler.InnerHandler;
214215

215-
if (currentHandler?.GetType() == typeof(SocketsHttpHandler))
216+
if (currentHandler is SocketsHttpHandler s)
216217
{
217-
hasSocketsHttpHandler = true;
218+
socketsHttpHandler = s;
218219
break;
219220
}
220221
}
221222

222-
Assert.IsTrue(hasSocketsHttpHandler);
223+
Assert.IsNotNull(socketsHttpHandler);
224+
Assert.AreEqual(true, socketsHttpHandler!.EnableMultipleHttp2Connections);
225+
Assert.AreEqual(TimeSpan.FromSeconds(10), socketsHttpHandler!.PooledConnectionLifetime);
223226
}
224227
#endif
225228

0 commit comments

Comments
 (0)