fredfmiranda / TesteS3SQS

0 stars 0 forks source link

Código com alto custo financeiro #7

Open tkrafael opened 1 year ago

tkrafael commented 1 year ago

https://github.com/fredfmiranda/TesteS3SQS/blob/f1af930c33819d4b2b3ead9f20294976f4872caa/App.cs#L38

Devido ao comportamento do SQS, em diversos momentos o ReceiveMessage não retornará resultados, forçando a aplicação a não fazer nada e eventualmente chamar de novo o ReceiveMessage.

Considerando uma aleatoriedade de post de novas mensagens no SQS, como seria possível tentar diminuir o número de ReceiveMessages de forma que ela tenha mais chance de pegar mensagens disponíveis no ReceiveMessage? Para efeito de comparação, o gráfico abaixo mostra exatamente essa situação em ambiente de produção: image

O vermelho são chamadas que retornaram vazio (na média 3/min) e o azul são chamadas que vieram com mensagens (na média 109/min). Esse mesmo gráfico há uns 10 meses tinha um comportamento de 50% de chamadas com mensagens e 50% sem mensagens. Colocada essa situação e avaliando o código, como seria possível evitar/diminuir esses requests?

fredfmiranda commented 1 year ago

@tkrafael então baseando-se no fato de que o SQS oferece dois tipos de filas - Standard e FIFO e que ambos suportam a opção de "long polling", que é uma forma mais eficiente de se recuperar mensagens da fila em comparação com "short polling" poderia-se adotar então essa abordagem. Para habilitar o Long Polling, você pode configurar o parâmetro WaitTimeSeconds na chamada ReceiveMessage.

No contexto do LongPooling: A solicitação de recebimento de mensagem espera até que uma mensagem esteja disponível ou até que um tempo limite seja atingido. Isso reduz o número de chamadas vazias de ReceiveMessage retornando mensagens de uma fila assim que elas se tornam disponíveis. var receiveMessageRequest = new ReceiveMessageRequest { QueueUrl = QueueUrl, WaitTimeSeconds = 20 // Máximo de 20 segundos };

Outra opção seria Backoff Exponencial: Se a fila estiver vazia, você pode implementar um algoritmo de backoff exponencial para espaçar progressivamente as chamadas subsequentes.

int delay = 1; // Começa com 1 segundo while (true) { var message = await ReceiveMessageFromQueue(); if (message == null) { // Não há mensagem, então aplique o backoff delay = Math.Min(30, delay * 2); // Cap de 30 segundos } else { // Processa a mensagem e reseta o delay ProcessMessage(message); delay = 1; } await Task.Delay(TimeSpan.FromSeconds(delay)); }

Outra opção na minha visão seria a de que se você tem informações estatísticas ou métricas em tempo real sobre o tráfego da fila, você pode adaptar a taxa de chamadas de acordo com esses dados. Por exemplo, se você sabe que a taxa de chegada de mensagens é baixa durante determinadas horas, você pode reduzir o número de chamadas durante esses períodos.