-
Notifications
You must be signed in to change notification settings - Fork 763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hedged Requests are not fired after connection timeouts #4654
Comments
This code reproduces the issue: using System;
using System.Net.Http;
using System.Net.Security;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http.Resilience;
var services = new ServiceCollection();
var clientBuilder = services
.AddHttpClient("ClientR9")
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
UseProxy = false,
Proxy = null,
ConnectTimeout = TimeSpan.FromSeconds(1),
SslOptions = new SslClientAuthenticationOptions
{
ClientCertificates = [],
RemoteCertificateValidationCallback = (_, _, _, _) => true
},
})
.AddStandardHedgingHandler(routing =>
{
routing.ConfigureOrderedGroups(g =>
{
g.Groups.Add(new UriEndpointGroup
{
Endpoints = new[] { new WeightedUriEndpoint { Uri = new Uri("https://localhost:3000") } }
});
g.Groups.Add(new UriEndpointGroup
{
Endpoints = new[] { new WeightedUriEndpoint { Uri = new Uri("https://microsoft.com") } }
});
});
})
.Configure(opt =>
{
opt.Hedging.MaxHedgedAttempts = 10;
opt.Hedging.Delay = TimeSpan.FromSeconds(11);
opt.Endpoint.CircuitBreaker.FailureRatio = 0.99;
opt.Endpoint.CircuitBreaker.SamplingDuration = TimeSpan.FromSeconds(900);
opt.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(200);
opt.Endpoint.Timeout.Timeout = TimeSpan.FromSeconds(200);
});
var provider = services.BuildServiceProvider();
var clientFactory = provider.GetRequiredService<IHttpClientFactory>();
var client = clientFactory.CreateClient("ClientR9");
try
{
var response = await client.GetAsync("https://localhost:3000");
Console.WriteLine(response.StatusCode);
}
catch (OperationCanceledException ex)
{
Console.WriteLine("Should never reach here but it does after 1 second");
} The issue is that |
This is where the exception is thrown and unfortunately there is no consistent way in identifying if it was a task cancelled from the connection timeout or task cancelled from a request timeout, in which case we probably don't want to retry / execute hedged requests: |
How about checking against |
I think that might work, what about the CancellationToken that is provided to the |
Description
If a connection establishment is failing with a timeout, configured on the SocketsHttpHandler, hedged requests are not generated and the whole pipeline fails.
Reproduction Steps
PreReq:
Expected behavior
The expected behavior is that "https://microsoft.com" endpoint is called and the pipeline succeeds.
Actual behavior
It is not actually called and a TaskCanceledException is thrown (coming from the HttpConnectionPool)
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
No response
The text was updated successfully, but these errors were encountered: