Usar a detecção de loop recursivo do Lambda para evitar loops infinitos - AWS Lambda

Usar a detecção de loop recursivo do Lambda para evitar loops infinitos

Ao configurar uma função do Lambda para gerar a saída para o mesmo serviço ou recurso que invoca a função, é possível criar um loop recursivo infinito. Por exemplo, uma função do Lambda pode gravar uma mensagem em uma fila do Amazon Simple Queue Service (Amazon SQS) que, em seguida, invoca a mesma função. Essa invocação faz com que a função grave outra mensagem na fila, que, por sua vez, invoca a função novamente.

Loops recursivos não intencionais podem resultar em cobranças inesperadas na sua Conta da AWS. Os loops também podem fazer com que o Lambda seja escalado e use toda a simultaneidade disponível de sua conta. Para ajudar a reduzir o impacto de loops não intencionais, o Lambda detecta determinados tipos de loops recursivos logo após eles ocorrerem. Por padrão, ao detectar um loop recursivo, o Lambda interrompe a invocação da função e notifica você. Se seu design usa padrões recursivos intencionalmente, é possível alterar a configuração padrão de uma função para permitir que ela seja invocada recursivamente. Consulte Permitir que uma função do Lambda seja executada em um loop recursivo Para mais informações.

Compreensão da detecção de loop recursivo

A detecção de loop recursivo no Lambda funciona com o rastreamento de eventos. O Lambda é um serviço de computação orientado a eventos que executa seu código de função quando ocorrem determinados eventos. Por exemplo, quando um item é adicionado a uma fila do Amazon SQS ou a um tópico do Amazon Simple Notification Service (Amazon SNS). O Lambda transmite eventos para a função como objetos JSON, que contêm informações sobre a alteração no estado do sistema. Quando um evento faz com que a função seja executada, isso é chamado de invocação.

Para detectar loops recursivos, o Lambda usa cabeçalhos de rastreamento do AWS X-Ray. Quando os Serviços da AWS compatíveis com a detecção de loop recursivo enviam eventos para o Lambda, esses eventos são anotados automaticamente com metadados. Quando a função do Lambda grava um desses eventos em outro AWS service (Serviço da AWS) compatível usando uma versão compatível de um AWS SDK, ela atualiza esses metadados. Os metadados atualizados incluem uma contagem do número de vezes que o evento invocou a função.

nota

Você não precisa habilitar o rastreamento ativo do X-Ray para que esse recurso funcione. Por padrão, a detecção de loop recursivo é ativada para todos os clientes da AWS. Não há cobranças pelo uso do recurso.

Uma cadeia de solicitações é uma sequência de invocações do Lambda causada pelo mesmo evento de acionamento. Por exemplo, imagine que uma fila do Amazon SQS invoque sua função do Lambda. Em seguida, a função do Lambda envia o evento processado para a mesma fila do Amazon SQS, que invoca a função novamente. Neste exemplo, cada invocação da função é direcionada para a mesma cadeia de solicitações.

Se a função for cerca de 16 vezes na mesma cadeia de solicitações, o Lambda interromperá automaticamente a próxima invocação da função nessa cadeia de solicitações e notificará você. Se a função estiver configurada com diversos acionadores, as invocações de outros acionadores não serão afetadas.

nota

Mesmo quando a configuração maxReceiveCount na política de redirecionamento da fila de origem é maior que 16, a proteção de recursão do Lambda não impede que o Amazon SQS repita a mensagem depois que um loop recursivo é detectado e encerrado. Quando o Lambda detecta um loop recursivo e descarta as invocações subsequentes, ele retorna uma RecursiveInvocationException para o mapeamento da origem do evento. Isso incrementa o valor receiveCount da mensagem. O Lambda continua refazendo a tentativa da mensagem e continua bloqueando as invocações de funções, até que o Amazon SQS determine que o maxReceiveCount foi excedido e envie a mensagem para a fila de mensagens não entregues configurada.

Se você tiver um destino em caso de falha ou uma fila de mensagens não entregues configurados para a função, o Lambda também enviará o evento da invocação interrompida para o destino ou a fila de mensagens não entregues. Se você configurar um destino ou uma fila de mensagens não entregues para a função, certifique-se de não usar um tópico do Amazon SNS ou uma fila do Amazon SQS que a função também use como um acionador de evento ou mapeamento da origem do evento. Se você enviar eventos para o mesmo recurso que invoca a função, poderá criar outro loop recursivo.

Serviços da AWS e SDKs compatíveis

O Lambda pode detectar somente loops recursivos que incluem determinados Serviços da AWS compatíveis. Para que os loops recursivos sejam detectados, a função também deve usar um dos AWS SDKs compatíveis.

Com suporte Serviços da AWS

No momento, o Lambda detecta loops recursivos entre suas funções, o Amazon SQS e o Amazon SNS. O Lambda também detecta loops compostos somente por funções do Lambda, que podem invocar umas às outras de forma síncrona ou assíncrona. Os seguintes diagramas apresentam alguns exemplos de loops que o Lambda pode detectar:

Diagramas de loops recursivos entre uma função do Lambda, o Amazon SNS e uma fila do Amazon SQS.

Quando outro AWS service (Serviço da AWS), como o Amazon DynamoDB ou o Amazon Simple Storage Service (Amazon S3), faz parte do loop, o Lambda não pode detectá-lo e interrompê-lo.

No momento, como o Lambda detecta somente loops recursivos envolvendo o Amazon SQS e o Amazon SNS, ainda é possível que loops envolvendo outros Serviços da AWS possam resultar no uso não intencional de suas funções do Lambda.

Para evitar cobranças inesperadas em sua Conta da AWS, recomendamos que você configure os alarmes do Amazon CloudWatch para alertar sobre padrões de uso incomuns. Por exemplo, é possível configurar o CloudWatch para notificar você sobre picos na simultaneidade ou nas invocações da função do Lambda. Também é possível configurar um alarme de faturamento para notificar você quando os gastos em sua conta excederem um limite especificado. Como alternativa, você pode usar o AWS Cost Anomaly Detection para alertas sobre padrões de faturamento incomuns.

AWS SDKs compatíveis

Para que o Lambda detecte loops recursivos, a função deve usar uma das seguintes versões do SDK ou superiores:

Runtime Versão mínima exigida do AWS SDK

Node.js

2.1147.0 (SDK versão 2)

3.105.0 (SDK versão 3)

Python

1.24.46 (boto3)

1.27.46 (botocore)

Java 8 e Java 11

2.17.135

Java 17

2.20.81

Java 21

2.21.24

.NET

3.7.293.0

Ruby

3.134.0

PHP

3.232.0

Go

SDK V2 (usar a versão mais recente)

Alguns runtimes do Lambda, como Python e Node.js, incluem uma versão do AWS SDK. Se a versão do SDK inclusa no runtime de sua função for inferior ao mínimo exigido, você poderá adicionar uma versão compatível do SDK ao pacote de implantação da função. Você também pode adicionar uma versão do SDK compatível à função usando uma camada do Lambda. Para obter uma lista dos SDKs inclusos em cada runtime do Lambda, consulte Runtimes do Lambda.

Notificações de loop recursivo

Quando o Lambda interrompe um loop recursivo, você recebe notificações por meio do AWS Health Dashboard e por e-mail. Você também pode usar as métricas do CloudWatch para monitorar o número de invocações recursivas que o Lambda interrompeu.

Notificações do AWS Health Dashboard

Quando o Lambda interrompe uma invocação recursiva, o AWS Health Dashboard exibe uma notificação na página de integridade da sua conta, em Problemas abertos e recentes. Observe que pode demorar até três horas após o Lambda interromper uma invocação recursiva até que essa notificação seja exibida. Para obter mais informações sobre como visualizar eventos da conta no AWS Health Dashboard, consulte Getting started with your AWS Health Dashboard – Your account health no Guia do usuário do AWS Health.

Alertas de e-mail

Quando o Lambda interrompe uma invocação recursiva da função pela primeira vez, ele envia um alerta por e-mail. O Lambda envia, no máximo, um e-mail a cada 24 horas para cada função em sua Conta da AWS. Após o Lambda enviar uma notificação por e-mail, você não receberá mais e-mails sobre essa função por mais 24 horas, mesmo que o Lambda interrompa outras invocações recursivas da função. Observe que pode demorar até três horas após o Lambda interromper uma invocação recursiva até que você receba este alerta por e-mail.

O Lambda envia alertas de e-mail de loop recursivo para o contato principal da conta e para o contato alternativo de operações da sua Conta da AWS. Para obter informações sobre como visualizar ou atualizar os endereços de e-mail em sua conta, consulte Updating contact information na Referência geral da AWS.

Métricas do Amazon CloudWatch

A métrica do CloudWatch RecursiveInvocationsDropped registra o número de invocações de função que o Lambda interrompeu porque a função foi invocada mais de 16 vezes em uma única cadeia de solicitações. O Lambda emite essa métrica logo após interromper uma invocação recursiva. Para visualizar essa métrica, siga as instruções em Exibir métricas no console do CloudWatch e escolha a métrica RecursiveInvocationsDropped.

Como responder a notificações de detecção de loop recursivo

Quando a função é invocada mais de 16 vezes pelo mesmo evento de acionamento, o Lambda interrompe a próxima invocação de função desse evento para interromper o loop recursivo. Para evitar a recorrência de um loop recursivo que o Lambda interrompeu, faça o seguinte:

  • Reduza a simultaneidade disponível da função para zero, pois isso limita todas as invocações futuras.

  • Remova ou desabilite o acionador ou o mapeamento da origem do evento que está invocando a função.

  • Identifique e corrija defeitos de código que gravam eventos no recurso da AWS que está invocando a função. Uma origem comum de defeitos ocorre quando você usa variáveis ​​para definir a origem e o destino do evento de uma função. Verifique se você não está usando o mesmo valor para ambas as variáveis.

Além disso, se a origem do evento para a função do Lambda for uma fila do Amazon SQS, considere configurar uma fila de mensagens não entregues na fila de origem.

nota

Certifique-se de configurar a fila de mensagens não entregues na fila de origem, e não na função do Lambda. A fila de mensagens não entregues que você configura em uma função é usada para a fila de invocação assíncrona da função, e não para filas de origem de evento.

Se a origem do evento for um tópico do Amazon SNS, considere adicionar um destino em caso de falha para a função.

Reduzir a simultaneidade disponível da função para zero (console)
  1. Abra a página Funções do console do Lambda.

  2. Escolha o nome da sua função.

  3. Escolha Controlar.

  4. Na caixa de diálogo Controlar a função, escolha Confirmar.

Remover um acionador ou mapeamento da origem do evento para a função (console)
  1. Abra a página Funções do console do Lambda.

  2. Escolha o nome da sua função.

  3. Escolha a guia Configuração e, em seguida, escolha Acionadores.

  4. Em Acionadores, selecione o acionador ou o mapeamento da origem do evento que deseja excluir e, em seguida, escolha Excluir.

  5. Na caixa de diálogo Excluir acionadores, escolha Excluir.

Desabilitar um mapeamento da origem do evento para a função (AWS CLI)
  1. Para descobrir o UUID para o mapeamento da origem do evento que você deseja desabilitar, execute o comando list-event-source-mappings da AWS Command Line Interface (AWS CLI).

    aws lambda list-event-source-mappings
  2. Para desabilitar o mapeamento da origem do evento, execute o comando update-event-source-mapping da AWS CLI apresentado a seguir.

    aws lambda update-event-source-mapping --function-name MyFunction \ --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 --no-enabled

Permitir que uma função do Lambda seja executada em um loop recursivo

Se seu design usa padrões recursivos intencionalmente, é possível configurar uma função do Lambda para permitir que ela seja invocada recursivamente. Recomendamos evitar usar loops recursivos em seu design. Erros de implementação podem levar a invocações recursivas usando toda a simultaneidade disponível da Conta da AWS e à cobrança inesperada de taxas em sua conta.

Importante

Se você usa loops recursivos, trate-os com cuidado. Implemente proteções de práticas recomendadas para minimizar os riscos de erros de implementação. Para saber mais sobre as práticas recomendadas para uso de padrões recursivos, consulte Padrões recursivos que causam a disparada de funções do Lambda no Serverless Land.

Você pode configurar funções para permitir loops recursivos usando o console do Lambda, a AWS Command Line Interface (AWS CLI) e a API PutFunctionRecursionConfig. Também é possível configurar a detecção de loop recursivo de uma função no AWS SAM e no AWS CloudFormation.

Por padrão, o Lambda detecta e encerra loops recursivos. A menos que o projeto use intencionalmente um loop recursivo, recomendamos não alterar a configuração padrão das suas funções.

Observe quem quando você configura uma função para permitir loops recursivos, a métrica do CloudWatch RecursiveInvocationsDropped não é emitida.

Console
Para permitir que uma função seja executada em um loop recursivo (console)
  1. Abra a página Funções do console do Lambda.

  2. Escolha o nome da sua função para abrir a página de detalhes da função.

  3. Escolha a guia Configuração e, em seguida, escolha Detecção de simultaneidade e recursividade.

  4. Ao lado de Detecção de loop recursivo, escolha Editar.

  5. Selecione Permitir loops recursivos.

  6. Escolha Salvar.

AWS CLI

A API PutFunctionRecursionConfig pode ser usada para permitir que sua função seja invocada em um loop recursivo. Especifique Allow para o parâmetro de loop recursivo. Por exemplo, você pode chamar essa API com o comando put-function-recursion-config da AWS CLI:

aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Allow

Você pode alterar a configuração da sua função de volta para a configuração padrão para que o Lambda encerre os loops recursivos ao detectá-los. Edite a configuração da sua função usando o console do Lambda ou a AWS CLI.

Console
Para configurar uma função para que os loops recursivos sejam encerrados (console)
  1. Abra a página Funções do console do Lambda.

  2. Escolha o nome da sua função para abrir a página de detalhes da função.

  3. Escolha a guia Configuração e, em seguida, escolha Detecção de simultaneidade e recursividade.

  4. Ao lado de Detecção de loop recursivo, escolha Editar.

  5. Selecione Encerrar loops recursivos.

  6. Escolha Salvar.

AWS CLI

A API PutFunctionRecursionConfig pode ser usada para configurar sua função para que o Lambda encerre loops recursivos ao detectá-los. Especifique Terminate para o parâmetro de loop recursivo. Por exemplo, você pode chamar essa API com o comando put-function-recursion-config da AWS CLI:

aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Terminate

Regiões com suporte para detecção de loops recursivos do Lambda

A detecção de loops recursivos do Lambda pode ser usada nas Regiões da AWS a seguir.

  • Leste dos EUA (Norte da Virgínia)

  • Leste dos EUA (Ohio)

  • Oeste dos EUA (N. da Califórnia)

  • Oeste dos EUA (Oregon)

  • África (Cidade do Cabo)

  • Ásia-Pacífico (Hong Kong)

  • Ásia-Pacífico (Mumbai)

  • Ásia-Pacífico (Osaka)

  • Ásia-Pacífico (Seul)

  • Ásia-Pacífico (Singapura)

  • Ásia-Pacífico (Sydney)

  • Ásia-Pacífico (Tóquio)

  • Canadá (Central)

  • Europa (Frankfurt)

  • Europa (Irlanda)

  • Europa (Londres)

  • Europa (Milão)

  • Europa (Paris)

  • Europa (Estocolmo)

  • Oriente Médio (Barém)

  • América do Sul (São Paulo)