We are experiencing an issue with HTTP requests where we are seeing that every 6 minutes a HTTP request is taking up to 162ms, on average these requests are taking 7ms. The metrics graph below shows a brief run of a K6 script calling our controller at a rate of 36 requests/minute. Im running K6 locally and both services in question are an AWS ECS instances. The slow response pattern persists for as long as I leave K6 running at this rate. The more you increase the rate at which K6 sends requests the less noticeable the spikes in the requestduration metric. I have metrics around the API controller which I am calling and they are showing an average time taken of 2ms so this is not the issue.
I initially thought this might be to do with the PooledConnectionIdleTimeout, but the default value for this is 1 minute in .NET 6 and later versions. We are using .Net 7. Not seeing anything on our infrastructure which would cause these spikes either.
My question is has anyone seen similar behaviour making HTTP requests, is it a possible issue with the code below?
We are adding our HTTP Client to our IServiceCollection as follows:
_builder.Services.AddHttpClient<IHttpClient, HttpClient>();
Our HTTP Client is as follows
public class HttpClient : IHttpClient
{
private readonly Metric.Client.IRecorder c_metrics;
private readonly System.Net.Http.HttpClient c_httpClient;
public HttpClient(
Metric.Client.IRecorder metrics,
System.Net.Http.HttpClient httpClient)
{
this.c_httpClient = httpClient;
}
public async Task<HttpResponseMessage> GetAsync(
string requestUrl,
string correlationId)
{
using (var _request = new HttpRequestMessage(HttpMethod.Get, requestUrl))
{
_request.Headers.Add("X-CorrelationId", correlationId);
using var _timer = this.c_metrics.StartTimer("requestduration");
return await this.c_httpClient.SendAsync(_request);
}
}
}
Our controller which we get our HttpClient from our DI container
public Controller(
IHttpClient httpClient)
{
this.c_httpClient = httpClient;
}
public async Task<IActionResult> GetAsync(
[FromQuery] Request request)
{
var _privateResponse = await this.c_httpClient.GetAsync(_requestUrl, _correlationId);
if (_privateResponse.StatusCode != HttpStatusCode.OK)
{
return StatusCode(500, new Error(Guid.Parse(_correlationId), "Internal server error"));
}
var _privateResponseContent = await _privateResponse.Content.ReadAsStringAsync();
return Ok(JsonSerializer.Deserialize<Response>(_privateResponseContent));
}