View a markdown version of this page

Novas tentativas para funções duráveis do Lambda - AWS Lambda

Novas tentativas para funções duráveis do Lambda

As funções duráveis fornecem recursos de novas tentativas automáticas que tornam suas aplicações resilientes a falhas transitórias. O SDK lida com novas tentativas em dois níveis: novas tentativas de etapas para falhas na lógica de negócios e novas tentativas de backend em caso de falhas de infraestrutura.

Novas tentativas de etapa

Quando ocorre uma exceção não detectada em uma etapa, o SDK faz uma nova tentativa da etapa automaticamente com base na estratégia de novas tentativas configurada. As novas tentativas de etapas são operações com pontos de verificação que permitem que o SDK suspenda a execução e continue posteriormente sem perder o andamento.

Comportamento de novas tentativas de etapa

A tabela a seguir descreve como o SDK lida com exceções em etapas:

Cenário O que acontece Medição de impacto
Exceção em etapa com novas tentativas restantes O SDK cria um ponto de verificação para a nova tentativa e suspende a função. Na próxima invocação, a etapa sofre nova tentativa com o retardo de recuo configurado. 1 operação + tamanho da carga útil de erro
Exceção em etapa sem novas tentativas restantes A etapa falha e emite uma exceção. Se o seu código do manipulador não capturar essa exceção, toda a execução falhará. 1 operação + tamanho da carga útil de erro

Quando uma etapa precisa ser repetida, o SDK verifica o estado de novas tentativas e sai da invocação do Lambda se nenhum outro trabalho estiver em execução. Isso permite que o SDK implemente retardos de recuo sem consumir recursos computacionais. A função é retomada automaticamente após o período de recuo.

Configuração de estratégias de novas tentativas de etapas

Configure estratégias de novas tentativas para controlar como as etapas tratam as falhas. É possível especificar o máximo de tentativas, os intervalos de recuo e as condições para novas tentativas.

Recuo exponencial com o máximo de tentativas:

TypeScript
const result = await context.step('call-api', async () => { const response = await fetch('https://api.example.com/data'); if (!response.ok) throw new Error(`API error: ${response.status}`); return await response.json(); }, { retryStrategy: (error, attemptCount) => { if (attemptCount >= 5) { return { shouldRetry: false }; } // Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s) const delay = Math.min(2 * Math.pow(2, attemptCount - 1), 300); return { shouldRetry: true, delay: { seconds: delay } }; } });
Python
def retry_strategy(error, attempt_count): if attempt_count >= 5: return RetryDecision(should_retry=False) # Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s) delay = min(2 * (2 ** (attempt_count - 1)), 300) return RetryDecision(should_retry=True, delay=delay) result = context.step( lambda _: call_external_api(), name='call-api', config=StepConfig(retry_strategy=retry_strategy) )

Recuo com intervalo fixo:

TypeScript
const orders = await context.step('query-orders', async () => { return await queryDatabase(event.userId); }, { retryStrategy: (error, attemptCount) => { if (attemptCount >= 3) { return { shouldRetry: false }; } return { shouldRetry: true, delay: { seconds: 5 } }; } });
Python
def retry_strategy(error, attempt_count): if attempt_count >= 3: return RetryDecision(should_retry=False) return RetryDecision(should_retry=True, delay=5) orders = context.step( lambda _: query_database(event['userId']), name='query-orders', config=StepConfig(retry_strategy=retry_strategy) )

Nova tentativa condicional (tentar novamente somente erros específicos):

TypeScript
const result = await context.step('call-rate-limited-api', async () => { const response = await fetch('https://api.example.com/data'); if (response.status === 429) throw new Error('RATE_LIMIT'); if (response.status === 504) throw new Error('TIMEOUT'); if (!response.ok) throw new Error(`API_ERROR_${response.status}`); return await response.json(); }, { retryStrategy: (error, attemptCount) => { // Only retry rate limits and timeouts const isRetryable = error.message === 'RATE_LIMIT' || error.message === 'TIMEOUT'; if (!isRetryable || attemptCount >= 3) { return { shouldRetry: false }; } // Exponential backoff: 1s, 2s, 4s (capped at 30s) const delay = Math.min(Math.pow(2, attemptCount - 1), 30); return { shouldRetry: true, delay: { seconds: delay } }; } });
Python
def retry_strategy(error, attempt_count): # Only retry rate limits and timeouts is_retryable = str(error) in ['RATE_LIMIT', 'TIMEOUT'] if not is_retryable or attempt_count >= 3: return RetryDecision(should_retry=False) # Exponential backoff: 1s, 2s, 4s (capped at 30s) delay = min(2 ** (attempt_count - 1), 30) return RetryDecision(should_retry=True, delay=delay) result = context.step( lambda _: call_rate_limited_api(), name='call-rate-limited-api', config=StepConfig(retry_strategy=retry_strategy) )

Desativar novas tentativas:

TypeScript
const isDuplicate = await context.step('check-duplicate', async () => { return await checkIfOrderExists(event.orderId); }, { retryStrategy: () => ({ shouldRetry: false }) });
Python
is_duplicate = context.step( lambda _: check_if_order_exists(event['orderId']), name='check-duplicate', config=StepConfig( retry_strategy=lambda error, attempt: {'should_retry': False} ) )

Quando a estratégia de novas tentativas retorna shouldRetry: false, a etapa falha imediatamente sem novas tentativas. Use isso para operações que não devam ser repetidas, como verificações de idempotência ou operações com efeitos colaterais que não possam ser repetidos com segurança.

Exceções fora das etapas

Quando ocorre uma exceção não detectada no código do manipulador, mas fora de qualquer etapa, o SDK marca a execução como com falha. Isso garante que os erros na lógica da aplicação sejam capturados e relatados adequadamente.

Cenário O que acontece Medição de impacto
Exceção no código do manipulador fora de qualquer etapa O SDK marca a execução como COM FALHA e retorna o erro. A exceção não sofre nova tentativa automaticamente. Tamanho da carga útil de erro

Para habilitar a nova tentativa automática para código propenso a erros, encapsule-o em uma etapa com uma estratégia de nova tentativa. As etapas fornecem uma nova tentativa automática com recuo configurável, enquanto as etapas externas do código falham imediatamente.

Repetições de invocação

As novas tentativas no nível de invocação são tratadas de forma diferente, dependendo de como a função durável do Lambda tenta ser invocada. A seguinte tabela descreve como os diferentes tipos de invocação podem influenciar as novas tentativas do nível de invocação.

Tipo de invocação O que acontece
Invocação síncrona O Lambda não repete automaticamente a invocação caso um erro ocorra durante a execução de uma função durável. As novas tentativas de falhas de invocação dependerão da origem da invocação síncrona. Por exemplo, usando o SDK AWS, o InternalFailure e o ThrottlingException são, por padrão, repetidos automaticamente.
Invocação assíncrona Se a execução de uma função durável falhar (por exemplo, ela entra no status FAILED, STOPPED ou TIMED_OUT), o Lambda não repetirá a execução. Isso é diferente das funções padrão do Lambda, em que ele tenta novamente a função em caso de falhas de invocação assíncrona. A configuração MaximumRetryAttempts para invocações assíncronas não se aplica a execuções duráveis. Caso você configure uma fila de mensagens não entregues (DLQ) para a função, o Lambda enviará o evento de acionamento para o DLQ.
Mapeamento da origem do evento (ESM) Por padrão, o Lambda tenta novamente o lote inteiro até que seja bem-sucedido. Em origens de fluxo (DynamoDB e Kinesis), é possível configurar o número máximo de vezes que o Lambda tentará novamente quando sua função retornar um erro. Consulte mapeamentos da origem do evento em lote. Para o Amazon SQS ESM, você pode configurar o máximo de novas tentativas através de um DLQ na fila original do Amazon SQS. Consulte configurar o Amazon SQS ESM. De maneira alternativa, você pode considerar um DLQ no nível da função e o Lambda enviará o evento de acionamento com falha para o DLQ. Consulte a função DLQ. Se você estiver interessado em receber um registro de eventos que falharam em todas as tentativas de processamento ou eventos de tentativas de processamento bem-sucedidas, pode configurar destinos para o ESM. Veja destinos assíncronos de invocação.
Acionador direto Isso depende do “Acionador”. Por exemplo, o Lambda processa funções acionadas pelas notificações de eventos do Amazon S3 de forma assíncrona. Consulte Processar notificações de eventos do Amazon SQS com o Lambda. O Lambda processa funções acionadas pelas notificações de eventos do Amazon SNS de forma assíncrona. Consulte Invocar funções do Lambda com notificações do Amazon SNS. O comportamento de nova tentativa de invocação assíncrona está acima na entrada da tabela “Invocação assíncrona”. Se o Amazon SNS não puder acessar o Lambda ou se a mensagem for rejeitada, o Amazon SNS tentará novamente em intervalos crescentes ao longo de várias horas. Para obter detalhes, consulte Confiabilidade nas Perguntas frequentes do Amazon SNS. A API Gateway invocará o Lambda de forma síncrona e retornará a resposta de erro genuína de volta para o solicitante. Consulte Repetições de invocação. O comportamento de nova tentativa de invocação síncrona está acima na entrada da tabela “Invocação síncrona”. Veja cada acionador direto para obter mais detalhes.

Novas tentativas de backend

As novas tentativas de backend ocorrem quando o Lambda encontra falhas de infraestrutura, erros de runtime ou quando o SDK não consegue se comunicar com o serviço de execução durável. O Lambda faz uma nova tentativa dessas falhas automaticamente para ajudar suas funções duráveis a se recuperarem de problemas transitórios de infraestrutura.

Cenários de nova tentativa de backend

O Lambda faz uma nova tentativa da sua função automaticamente quando encontra os cenários a seguir:

  • Erros de serviço internos: quando o Lambda ou o serviço de execução durável retorna um erro 5xx, indicando um problema temporário no serviço.

  • Limitação: quando sua função sofre controle de utilização devido a limites de simultaneidade ou cotas de serviço.

  • Tempos limite: quando o SDK não consegue alcançar o serviço de execução durável dentro do período de tempo limite.

  • Falhas na inicialização da sandbox: quando o Lambda não consegue inicializar o ambiente de execução.

  • Erros de runtime: quando o runtime do Lambda encontra erros fora do seu código de função, como erros de falta de memória ou falhas no processo.

  • Erros de token de ponto de verificação inválido: quando o token de ponto de verificação não é mais válido, normalmente devido a mudanças de estado do lado do serviço.

A tabela a seguir descreve como o SDK trata esses cenários.

Cenário O que acontece Medição de impacto
Erro de runtime fora do manipulador durável (OOM, tempo limite, falha) O Lambda automaticamente faz uma nova tentativa de invocação. O SDK é reproduzido a partir do último ponto de verificação, ignorando as etapas concluídas. Tamanho da carga útil de erro + 1 operação por nova tentativa
Erro de serviço (5xx) ou tempo limite ao chamar as APIs CheckpointDurableExecution / GetDurableExecutionState O Lambda automaticamente faz uma nova tentativa de invocação. O SDK reproduz a partir do último ponto de verificação. Tamanho da carga útil de erro + 1 operação por nova tentativa
Controle de utilização (429) ou token de ponto de verificação inválido ao chamar as APIs CheckpointDurableExecution / GetDurableExecutionState O Lambda automaticamente faz uma nova tentativa de invocação com recuo exponencial. O SDK reproduz a partir do último ponto de verificação. Tamanho da carga útil de erro + 1 operação por nova tentativa
Erro do cliente (4xx, exceto 429 e token inválido) quando as APIs CheckpointDurableExecution / GetDurableExecutionState O SDK marca a execução como COM FALHA. Nenhuma nova tentativa automática ocorre porque o erro indica um problema permanente. Tamanho da carga útil de erro

As novas tentativas de backend usam o recuo exponencial e prosseguem até que a função tenha êxito ou o tempo limite de execução seja atingido. Durante a reprodução, o SDK ignora os pontos de verificação concluídos e continua a execução da última operação com êxito, garantindo que sua função não reexecute o trabalho concluído.

Práticas recomendadas de novas tentativas

Siga estas práticas recomendadas ao configurar estratégias de novas tentativas:

  • Configure estratégias de novas tentativas explícitas: não confie no comportamento padrão de novas tentativas na produção. Configure estratégias de novas tentativas explícitas com o máximo de tentativas e intervalos de recuo apropriados para seu caso de uso.

  • Use novas tentativas condicionais: - implemente a lógica shouldRetry para repetir somente erros transitórios (limites de taxa, tempos limite) e antecipe-se à falha em erros permanentes (falhas de validação, não encontrado).

  • Defina o máximo de tentativas apropriadas: equilíbrio entre resiliência e tempo de execução. Muitas tentativas podem atrasar a detecção de falhas, enquanto poucas podem causar falhas desnecessárias.

  • Use o recuo exponencial: o recuo exponencial reduz a carga nos serviços subsequentes e aumenta a probabilidade de recuperação de falhas transitórias.

  • Encapsule o código propenso a erros em etapas: o código fora das etapas não pode sofrer novas tentativas automaticamente. Encapsule chamadas externas de API, consultas de banco de dados e outras operações sujeitas a erros em etapas com estratégias de novas tentativas.

  • Monitore as métricas de novas tentativas: acompanhe as operações de novas tentativas de etapas e falhas de execução no Amazon CloudWatch para identificar padrões e otimizar estratégias de novas tentativas.