O blog da AWS

Detecção e interrupção de loops recursivos em funções do AWS Lambda

Por Julian Wood, Aneel Murari, e Pawan Puthran

 

Este post foi escrito por Pawan Puthran, principal especialista sem servidor da TAM, Aneel Murari, arquiteta sênior de soluções especialista sem servidor, Shree Shrikhande, gerente sênior de produtos do AWS Lambda e adaptado para Português por Daniel ABIB, arquiteto de soluções sênior para Entreprise.

O AWS Lambda agora permite um controle de recursão para detectar e interromper a execução de funções do Lambda em um loop recursivo ou infinito.No lançamento, esse recurso está disponível para integrações do Lambda com o Amazon Simple Queue Service (Amazon SQS), o Amazon SNS ou ao invocar funções diretamente usando a API de invocação. O AWS Lambda agora detecta funções que parecem estar sendo executadas em um loop recursivo e descarta as solicitações após exceder 16 invocações.Isso pode ajudar a reduzir os custos de invocações inesperadas devido à recursão. Você recebe notificações sobre essa ação por meio do AWS Health Dashboard, por e-mail ou configurando os alarmes do Amazon CloudWatch.

Visão geral

Você pode invocar funções do Lambda de várias maneiras. Os serviços da AWS geram eventos que invocam funções do Lambda, e as funções do Lambda podem enviar mensagens para outros serviços da AWS. Na maioria das arquiteturas, o serviço ou recurso que invoca uma função Lambda deve ser diferente do serviço ou recurso para o qual a função é enviada. Devido a erros de configuração ou de codificação, uma função pode enviar um evento processado para o mesmo serviço ou recurso que invoca a função Lambda, causando um loop recursivo.

O AWS Lambda agora detecta a função em execução em um loop recursivo entre os serviços suportados, após exceder 16 invocações. Ele retorna uma RecursiveInvocationException para o chamador/invocador. Não há cobrança adicional por esse recurso. Para invocações assíncronas, o Lambda envia o evento para uma dead-letter queue (DLQ) em caso de falha, se uma estiver configurada.

Veja a seguir um exemplo de um sistema de processamento de pedidos.

Image processing system

Sistema de processamento de pedidos

  1. Uma nova mensagem com informações do pedido é enviada para a fila SQS de origem.
  2. O AWS Lambda consome a mensagem da fila de origem usando um ESM (event source mapping).
  3. A função Lambda processa a mensagem e envia a mensagem de pedidos atualizada para uma fila SQS de destino usando a API SQS SendMessage.
  4. A fila de origem tem uma dead-letter queue (DLQ) configurada para lidar com qualquer mensagem com falha ou não processada.
  5. Devido a uma configuração incorreta, a função Lambda envia a mensagem para a fila SQS de origem em vez da fila de destino. Isso causa um loop recursivo de invocações de funções Lambda.

Para explorar o código desse exemplo, consulte o repositório do GitHub.

No exemplo anterior, após 16 invocações, o AWS Lambda lança uma RecursiveInvocationException para o ESM. O ESM para de invocar a função Lambda e, quando o maxReceiveCount é excedido, o SQS move a mensagem para as filas de origem configuradas como DLQ.

Você recebe uma notificação do AWS Health Dashboard com etapas para solucionar problemas da função.

AWS Health Dashboard notification

Notificação do AWS Health Dashboard

Você também recebe uma notificação por e-mail para o endereço de e-mail registrado na conta.

Email notification

Notificação por  e-mail.

O AWS Lambda emite uma métrica recursiveInvocationsDropped no CloudWatch, que você pode ver no console do CloudWatch.

RecursiveInvocationsDropped CloudWatch metric

Invocações recursivas eliminaram a métrica do CloudWatch

Como o Lambda detecta a recursão?

Para que o Lambda detecte loops recursivos, sua função deve usar uma das versões suportadas do AWS SDK ou superior.

O AWS Lambda usa uma primitiva de cabeçalho de rastreamento do AWS X-Ray chamada “Lineage” para rastrear o número de vezes que uma função foi invocada com um evento. Quando seu código de função envia um evento usando uma versão compatível do AWS SDK, o AWS Lambda incrementa o contador no cabeçalho. Se sua função for então invocada com o mesmo evento acionador mais de 16 vezes, o AWS Lambda interromperá a próxima invocação desse evento. Você não precisa configurar o rastreamento ativo do X-Ray para que esse recurso funcione.

Um exemplo de cabeçalho se parece com:

X-Amzn-Trace-Id:Root=1-645f7998-

4b1e232810b0bb733dba2eab;Parent=5be88d12eefc1fc0;Sampled=1;Lineage=43e12f0f:5

43e12f0f é o hash de um recurso, neste caso uma função Lambda. 5 é o número de vezes que essa função foi invocada com o mesmo evento. A lógica da geração de hash, codificação e tamanho do cabeçalho pode mudar no futuro. Você não deve criar nenhuma funcionalidade com base nisso.

Ao usar um ESM para consumir mensagens do SQS, depois que o valor maxReceiveCount for excedido, a mensagem é enviada para a DLQ configurada da fila de origem. Quando o AWS Lambda detecta um loop recursivo e descarta as invocações subsequentes, ele retorna uma RecursiveInvocationException para o ESM. Isso incrementa o valor de maxReceiveCount. Quando o ESM tenta processar eventos automaticamente, com base na configuração de tratamento de erros, essas novas tentativas não são consideradas invocações recursivas.

Ao usar o SQS, você também pode agrupar várias mensagens em um evento Lambda. Quando o tamanho do lote de mensagens é maior que 1, o AWS Lambda usa o valor máximo dentro do lote de mensagens. Ele descarta todo o lote se o valor exceder 16.

Detecção de recurso em ação

Você pode implantar um exemplo de aplicativo de exemplo no repositório do GitHub para testar a detecção de loop recursivo do AWS Lambda. O aplicativo inclui uma função Lambda que lê de uma fila SQS e grava mensagens de volta na mesma fila SQS.

Como pré-requisitos, você deve instalar:

Para implantar o aplicativo:

  1. Defina sua região da AWS:
  2. Clone o repositório do GitHub
  3. Use o AWS SAM para criar e implantar os recursos em sua conta da AWS. Insira um nome de pilha, como lambda-recursion, quando solicitado. Aceite os valores padrão restantes.

Para testar o aplicativo:

  1. Salve o nome da fila SQS em uma variável de ambiente local:
    SOURCE_SQS_URL=$(aws cloudformation describe-stacks \ --region $REGION \ --stack-name lambda-recursion \ --query 'Stacks[0].Outputs[?OutputKey==`SourceSQSqueueURL`].OutputValue' --output text
  2. Publish a message to the source SQS queue:
    aws sqs send-message --queue-url $SOURCE_SQS_URL --message-body '{"orderId":"111","productName":"Bolt","orderStatus":"Submitted"}' --region $REGION

Isso invoca a função Lambda, que grava a mensagem de volta na fila.

Para verificar se o AWS Lambda detectou a recursão:

  1. Navegue até o console do CloudWatch. Escolha Todas as métricas em Métricas no painel esquerdo e pesquise RecursiveInvocationsDropped.

    Find RecursiveInvocationsDropped.

    Encontre invocações recursivas descartadas.

  2. Escolha Lambda > Por nome da função e escolha RecursiveInvocationsDropped para a função que você criou. Em Métricas gráficas, altere a estatística para soma e Período para 1 minuto. Você verá um registro. Atualize se você não ver a métrica após alguns segundos.

Metrics sum view

Visualização da soma demétricas

Ações a serem tomadas quando o Lambda interrompe um loop recursivo

Quando você recebe uma notificação sobre recursão em sua conta, as etapas a seguir podem ajudar a resolver o problema.

  • Para interromper novas tentativas de invocação enquanto você corrige o problema de configuração subjacente, defina a simultaneidade da função como 0. Isso funciona como um botão de desligamento da função Lambda. Você pode escolher o botão “Throttle” no console do Lambda ou usar a API PutFunctionConcurrency para definir a simultaneidade da função como 0.
  • Você também pode desativar ou excluir o mapeamento ou o gatilho da origem do evento para a função Lambda.
  • Verifique o código e a configuração da função Lambda para detectar quaisquer defeitos de código que criem loops. Por exemplo, verifique suas variáveis de ambiente para garantir que você não esteja usando a mesma fila do SQS ou tópico do SNS como origem e destino.
  • Se uma fila SQS for a origem do evento para sua função Lambda, configure uma DLQ na fila de origem.
  • Se um tópico do SNS for a origem do evento, configure um destino em caso de falha para a função Lambda.

Desativando a detecção de recursão

Você pode ter casos de uso válidos em que a recursão do Lambda seja intencional como parte de seu design. Nesse caso, tenha cuidado e implemente grades de proteção adequadas para evitar cobranças inesperadas em sua conta. Para saber mais sobre as melhores práticas para usar padrões de invocação recursiva, consulte Padrões recursivos que causam funções Lambda descontroladas no Guia do operador do AWS Lambda.

Esse recurso é ativado por padrão para interromper os loops recursivos. Para solicitar a desativação da sua conta, entre em contato com o AWS Support.

Conclusão

O controle de recursão Lambda para SQS e SNS detecta e interrompe automaticamente as funções em execução em um loop recursivo ou infinito. Isso pode ser devido a erros de configuração ou codificação. O controle de recursão ajuda a reduzir o uso inesperado com serviços Lambda e downstream. A postagem também explica como o AWS Lambda detecta e interrompe loops recursivos e notifica você por meio do AWS Health Dashboard para solucionar problemas com a função.

Para saber mais sobre o recurso, visite o Guia do desenvolvedor do AWS Lambda.

Para obter mais recursos de aprendizado sem servidor, visite Serverless Land.

 

Este artigo foi traduzido do Blog da AWS em Inglês.


Sobre os autores

Julian Wood

 

 

 

 

Aneel Murari

 

 

 

 

Pawan Puthran

 

 

 

 

Tradutor

Daniel Abib é Enterprise Solution Architect na AWS, com mais de 25 anos trabalhando com gerenciamento de projetos, arquiteturas de soluções escaláveis, desenvolvimento de sistemas e CI/CD, microsserviços, arquitetura Serverless & Containers e segurança. Ele trabalha apoiando clientes corporativos, ajudando-os em sua jornada para a nuvem.

https://www.linkedin.com/in/danielabib/