O blog da AWS

Protegendo sua Conta AWS de Gastos Inesperados Usando Soluções Serveless

Por Luiz Yanai, Arquiteto de Soluções e especialista em Serverless, AWS Brasil

O ambiente em nuvem AWS permite que instanciemos diversos recursos em questão de minutos com facilidade para suportar uma demanda crescente de requisições. Contudo, existem casos em que o crescimento de requisições se deve a erros de execução da aplicação, seja por problema no código ou por indisponibilidade momentânea de algum recurso. Em ambos os casos, para o modelo de precificação de nuvem, paga-se somente pelo uso do serviço. No entanto, no segundo caso iremos pagar por um tráfego que não necessariamente está gerando valor para o negócio. Além disso, dependendo da implementação utilizada, pode se criar um custo elevado de forma inesperada. Este artigo apresenta um cenário real onde este problema aconteceu e as alternativas arquiteturais para evitá-lo.

O cenário onde o problema foi observado é semelhante ao desenho abaixo. É uma arquitetura serverless comum utilizando os serviços Amazon Simple Queue Service (SQS), AWS Lambda e Amazon DynamoDB.

Figura 1 – Cenário comum de processamento assíncrono de mensagens

 

CENÁRIOS COMUNS DE ERROS

Na arquitetura apresentada acima, diversos tipos de erros podem ocorrer gerando alguns comportamentos específicos:

  • Timeout da função ‘function A’: Em uma função Lambda é possível definir o timeout de execução da rotina até o valor máximo de 15 minutos. Se o tempo de execução da função superar o valor usado na configuração, o processamento é interrompido, isto é, não é finalizado com sucesso e a mensagem não é removida da fila SQS de entrada. Após a expiração do tempo de invisibilidade da mensagem, outra instância da função Lambda pode tentar realizar o processamento desta mesma mensagem. Na configuração padrão de um fila SQS, não é definida uma fila do tipo dead letter queue (DLQ) para receber as mensagens não processadas (figura 2). Logo, caso haja uma má configuração do timeout e nenhuma política de DLQ tenha sido configurada, a mensagem será reprocessada diversas vezes enquanto a mensagem estiver na fila (definido pela propriedade configurável MessageRetentionPeriod que por padrão são 4 dias) consumindo tempo de execução de computação do Lambda.

Figura 2 – Configurações de uso de DLQ em uma fila do SQS

  • Timeout da função ‘function A.1’: No cenário acima, a função Lambda ‘function A.1’ está sendo invocada de forma assíncrona pela função ‘function A’. Da mesma forma que na situação anterior, durante a execução da rotina pode-se deparar com um erro de timeout. Como é uma chamada assíncrona, a função Lambda faz uso de uma fila interna para controlar o processamento. Existe um comportamento padrão no processamento: se ocorrer erro na função antes da execução, Lambda retorna o evento para a fila e tenta executar a função novamente por até 6 horas. Se o erro acontecer após a execução, Lambda tenta executar até 2 vezes. Recentemente foi incluído o suporte para ajuste destes dois parâmetros: tempo máximo de vida do evento na fila (60 s até 6 horas) e máximo de tentativas para chamadas assíncronas. É possível também configurar uma fila DLQ para receber mensagens não processadas de forma assíncrona pela função Lambda.

Figura 3 – Configurações de processamento assíncrono do Lambda

  • Indisponibilidade do recurso externo ‘External resource’: Por algum problema de indisponibilidade ou erro de comunicação, um serviço externo pode apresentar problemas para ser invocado pela função Lambda. Imaginando-se um cenário onde um registro já tenha sido inserido em uma tabela do DynamoDB e depois ocorre um erro na chamada do recurso externo, se não houver um tratamento de exceções e compensação e a função Lambda retornar erro, serão gerados registros duplicados no DynamoDB devido às novas tentativas de execução que o Lambda faz por padrão.

Em todos os cenários acima, os erros gerados podem levar a um crescimento no uso de tempo de computação das funções Lambda e também a geração de requisições duplicadas gerando gastos extras.

 

ENTENDENDO O CONSUMO DOS SERVIÇOS

Para entender o impacto financeiro na ocorrência dos erros acima é importante conhecer a forma de cobrança dos serviços envolvidos. Nas tabelas abaixo são listados os principais fatores que impactam a precificação do uso dos serviços para a arquitetura anterior. Os valores são baseados na região de North Virginia.

SQS

O SQS tem custo baseado principalmente na quantidade de requisições. O reprocessamento de mensagens pode levar a aumento de custo. Por isto, deve-se avaliar bem a quantidade de tentativas de reprocessamento antes do envio para uma fila de falha ou fila DLQ.

Lambda

Para o Lambda, o que deve impactar mais o custo é o consumo de tempo de computação. Por isso é importante controlar o timeout e o comportamento das mensagens para atender aos requisitos da aplicação e ao mesmo tempo evitar consumo desnecessário.

DynamoDB

Para o DynamoDB, se for utilizada a modalidade de capacidade provisionada, um crescimento na quantidade de requisições não deve impactar o custo porque requisições acima do suportado pela capacidade provisionada receberão throttle e não terão custo. Caso seja utilizada a opção on demand, a capacidade se ajusta à demanda e pode gerar gastos extras para as requisições duplicadas.

 

COMO PROTEGER SUA CONTA

Uma forma fácil e prática de proteger sua conta AWS de custos além do esperado é utilizar boas práticas de monitoração de uso de recursos. As duas principais opções para fazer este controle são apresentados na figura abaixo.

Figura 4 – Notificação de consumo usando Amazon CloudWatch e AWS Budgets

O Amazon CloudWatch é a solução padrão para monitoria dos seus recursos na nuvem AWS (e em alguns casos até on premises) e permite, por exemplo, monitorar os gastos estimados na sua conta e disparar notificações através da definição de um alarme. O alarme contabiliza a métrica de gastos e compara com um threshold definido pelo usuário. Caso o valor ultrapasse o valor definido, uma notificação pode ser enviada utilizando um tópico SNS.

Outra opção é utilizar o AWS Budgets, que funciona de forma semelhante, mas permite definir budgets por serviço ou grupo de serviços e também controlar o uso de instâncias reservadas e do novo recurso de Saving Plans. O uso de um tópico SNS permite a notificação por diferentes meios como e-mail, mensagem SMS e até realizar uma lógica customizada via AWS Lambda.

Algumas vezes, uma simples notificação pode não ser eficaz para uma ação mais rápida. Neste caso, a recomendação é fazer a automação via função Lambda para, por exemplo, desabilitar uma origem de eventos da função Lambda que apresenta o problema. É possível desabilitar o consumo dos eventos via AWS SDK com a operação updateEventSourceMapping.

Com relação a comunicação assíncrona usando AWS Lambda, uma nova funcionalidade que permite um maior controle no tratamento de erros de integração é o AWS Lambda Destinations.

Figura 5 – Configuração de destinos de eventos de sucesso/falha usando a funcionalidade de Lambda Destinations

Na configuração do Lambda Destinations é possível definir o destino das mensagens dos eventos na ocorrência de erros e também de sucesso. Os destinos podem ser tanto uma outra função Lambda, um tópico SNS, uma fila SQS ou o Amazon EventBridge.

Figura 6 – Configurações de Lambda Destionations no console AWS

 

Conclusão e próximos passos

Nesse blog post, descrevemos novas funcionalidades que possibilitam proteger suas contas AWS de surpresas indesejáveis na fatura devido ao consumo elevado de recursos usando serviços serverless e boas práticas de gestão.

Para saber mais sobre os recursos e funcionalidades utilizadas, visite os seguintes links:

https://docs.thinkwithwp.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html

https://thinkwithwp.com/about-aws/whats-new/2019/11/aws-lambda-supports-max-retry-attempts-event-age-asynchronous-invocations/

https://docs.thinkwithwp.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#updateEventSourceMapping-property


Sobre o autor

Luiz Yanai é arquiteto de soluções na AWS e especialista em tecnologias Serverless, atua auxiliando clientes de diversos segmentos en suas jornadas para a nuvem. Com mais de 15 anos de experiência em arquitetura e desenvolvimento de soluções envolvendo sistemas empresariais e de missão crítica.