Carlos Siestrup
Carlos Siestrup

Reputation: 1216

HttpClient taking too long

I created a .Net Framework 4.7.2 console app that concurrently makes many requests in an API hosted in AWS. My problem is that the requests are taking too long.

The API's response time is usually 100ms-400ms according to the taget group monitoring in AWS console but in my application the time elapsed of each request starts at 1 second and keeps increasing until 11 seconds.

I'm already aware that HttpClient doesn't close connections properly so we shouldn't use using and instead always use one instance for each application.

I already found a similar question but the answer didn't solve it.

When I set MaxDegreeOfParallelism to 1, the response time in the application is similar to the app. This seem to be problem that occurs in HttpClient in a multi thread.

This is how i'm doing the requests :

public static class RequestMaker
{
    private static readonly string _urlHttp = "http://apidomain.com/api/apiname";
    private static readonly HttpClient _httpClient = new HttpClient();
    public static async Task<string> PostAsync(string postData)
    {
        bool IsSuccessStatusCode = false;
        int maxRetries = 5;
        int count = 0;
        do
        {
            try
            {
                Stopwatch watcher = Stopwatch.StartNew();
                using (HttpContent content = new StringContent(postData, Encoding.UTF8, "application/json"))
                using (HttpResponseMessage result = await _httpClient.PostAsync(_urlHttp, content).ConfigureAwait(false))
                {
                    watcher.Stop();
                    Console.WriteLine("Elapsed = " + watcher.ElapsedMilliseconds.ToString("N0"));
                    IsSuccessStatusCode = result.IsSuccessStatusCode;
                    if (IsSuccessStatusCode)
                        return await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                    count++;
                    if (count > maxRetries)
                        return "";

                    Console.WriteLine($"Retrying request because of request status code {result.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                count++;
                if (count > maxRetries)
                    return "";
            }
        } while (!IsSuccessStatusCode);

        return "";
    }
}

This is my function calling the request concurrently :

static void RunBatchMany(List<string> list)
{
    var getCustomerBlock = new TransformBlock<string, long>(
        async lstRec =>
        {
            ApiInputObject apiInput = new ApiInputObject();
            
            // PrepareInputObject
            string postData = JsonConvert.SerializeObject(apiInput);

            Stopwatch watcher = Stopwatch.StartNew();
            string json = await RequestMaker.PostAsync(postData);
            ApiResponseObject res = JsonConvert.DeserializeObject<ApiResponseObject>(json);
            watcher.Stop();
            return watcher.ElapsedMilliseconds;

        }, new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = 8
        });

    foreach (var id in list)
        getCustomerBlock.Post(id);

    getCustomerBlock.Complete();
    getCustomerBlock.Completion.Wait();
}

Upvotes: 0

Views: 1062

Answers (0)

Related Questions