Запросы на тайм-аут при применении легкой нагрузки к. Net Core Web Api - PullRequest
2 голосов
/ 09 февраля 2020

У меня есть API, который в основном получает запрос и отправляет его в очередь SQS, ничего сложного.

[HttpPost]
public ActionResult Post([FromBody]object message, [FromHeader] string source)
    {
        if (message== null)
            return new UnsupportedMediaTypeResult();
        if (PublishMessageToSQS(JsonConvert.SerializeObject(message),source))
            return StatusCode(201);
        return StatusCode(500);
    }
    private bool PublishMessage(string message, string source)
    {
        try
        {
            RetryWhenException.Do(
                () =>
                {
                    SendMessageRequest request = new SendMessageRequest()
                    {
                        MessageBody = message,
                        MessageAttributes = new Dictionary<string, MessageAttributeValue>(),
                        QueueUrl = "my queue",
                    };
                    if (!string.IsNullOrEmpty(source))
                        request.MessageAttributes.Add("source", new MessageAttributeValue()
                        {
                            StringValue = source,
                            DataType = "String"
                        });
                    var result = sqsClient.SendMessageAsync(request).Result;
                }, 3, 1000);
            return true;
        }
        catch (Exception e)
        {
            //log
            throw;
        }
    }

Этот API упакован в контейнер и развернут в AWS ECS на компьютере с низким уровнем ресурсов (0,25 VCpu , 512 МБ ОЗУ).

При небольшой нагрузке на API (10 запросов в секунду) запросы начинают время ожидания через некоторое время.

Я перестал получать тайм-ауты при применении одного из:

1 - использовать больше ресурсов (2 VCPU, 4 ГБ ОЗУ)

2 - сделать мое действие асинхронным c.

[HttpPost]
public async Task<ActionResult> Post([FromBody]object message, [FromHeader] string source)
    {
        if (message== null)
            return new UnsupportedMediaTypeResult();
        if (await PublishMessageToSQS(JsonConvert.SerializeObject(message), source))
            return StatusCode(201);
        return StatusCode(500);
    }

private async Task<bool> PublishMessage(string message, string source)
    {
        try
        {
            await RetryWhenException.Do(
             async () =>
              {
                  SendMessageRequest request = new SendMessageRequest()
                  {
                      MessageBody = message,
                      MessageAttributes = new Dictionary<string, MessageAttributeValue>(),
                      QueueUrl = "my queue",
                  };
                  if (!string.IsNullOrEmpty(source))
                      request.MessageAttributes.Add("source", new MessageAttributeValue()
                      {
                          StringValue = source,
                          DataType = "String"
                      });
                  var result = await sqsClient.SendMessageAsync(request);
              }, 3, 1000);
            return true;
        }
        catch (Exception e)
        {
         //log
         throw;
        }
    }

RetryWhenException code:

public static class RetryWhenException
{
    public static void Do(Action action, int maxAttemptCount = 3, int retryInterval = 1000)
    {
        var exceptions = new List<Exception>();
        for (var attempted = 0; attempted < maxAttemptCount; attempted++)
        {
            try
            {
                if (attempted > 0)
                {
                    Thread.Sleep(retryInterval);
                }
                action();
                return;
            }
            catch (Exception ex)
            {
                exceptions.Add(ex);
            }
        }
        throw new AggregateException(exceptions);
    }
}

Я знаю, что Asyn c освобождает потоки, но переход на SQS не так уж и дорог, а количество запросов не так велико.

Я действительно не понимаю, почему у меня были тайм-ауты при применении такой низкой полезной нагрузки, и почему asyn c добился цели, любое объяснение?

...