O Amazon Simple Queue Service (SQS) é um serviço poderoso projetado para gerenciar as necessidades de mensagens de microsserviços robustos e desacoplados.
Ele se integra fortemente ao AWS Lambda, seu parceiro nativo, como destino alvo.
O SQS pode acionar uma função Lambda como seu alvo e enviar os itens do lote como entrada.
Entretanto, no lado da função Lambda, lidar com essa entrada pode ser complicado, especialmente quando erros e tentativas surgem.
Este é o terceiro artigo de uma série de três partes sobre as melhores práticas do SQS
Neste artigo, você aprenderá sobre as práticas recomendadas para filas de mensagens mortas e como lidar com falhas de maneira correta e automatizada, redirecionando os itens de volta para a fila de origem.
Você pode encontrar todos os exemplos de código Python do AWS CDK aqui .
Você pode encontrar todos os exemplos de código Lambda Python aqui .
Outros artigos da série:
O primeiro artigo ensinará como lidar com eficiência com lotes do Amazon SQS com o AWS Lambda Powertools para Python e exemplos de código do AWS CDK.
O segundo artigo ensinará você a lidar com falhas de processamento em lote do Amazon SQS e dominar as tentativas automáticas com o AWS Lambda Powertools para exemplos de código Python e AWS CDK.
Índice
SQS Re:cap
No primeiro artigo, em minhas melhores práticas de SQS, definimos o padrão de função SQS para Lambda. Implementamos o código de infraestrutura do AWS CDK e o código do manipulador de função Lambda.
No segundo artigo, adicionamos a noção de novas tentativas à função Lambda e usamos a capacidade de marcar falhas parciais de volta ao SQS.
No entanto, não lidamos com casos de uso em que, no final, todas as tentativas falharam.
Observe que este artigo se baseia nos exemplos de código dos artigos anteriores.
Melhores práticas para filas de mensagens mortas do SQS
Vamos revisar as práticas recomendadas de processamento em lote e novas tentativas do SQS que definimos nos artigos anteriores no diagrama abaixo:
(1) O SQS aciona uma função Lambda com itens de lote. A função Lambda itera sobre os itens de lote e manipula cada item e tenta novamente seu processamento (1a no diagrama, se necessário) com ' tenacity '.
(2) A função marca para o SQS quais itens falharam no processamento (após várias tentativas de repetição) ou termina com uma exceção se o lote inteiro falhou. Se todos os itens forem processados com sucesso, a função marca que zero itens falharam no processamento.
(3) Se o Lambda marcou itens como falhados no processamento, o SQS invocará a função novamente com um lote contendo apenas os itens com falha assim que o tempo limite de visibilidade do SQS tiver passado.
Lidando com falhas
Às vezes, você tenta e tenta novamente, mas simplesmente não funciona. Às vezes, um serviço externo do qual você depende está inativo, ou você pode ter um bug no seu próprio código. Não importa a causa, seu Lambda não conseguiu concluir o processamento de um item e, eventualmente, o processamento falha após um número predefinido de tentativas de repetição.
O que fazemos?
Queremos implementar outro conceito: uma fila de mensagens mortas (DLQ).
Enviaremos todos os itens de processamento eventualmente com falha para outro SQS chamado de dead letter queue. Vamos revisar o diagrama atualizado com uma nova etapa, etapa número quatro.
(4) O SQS enviará automaticamente os itens eventualmente com falha para outro SQS, o DLQ.
Agora que todos os itens com falha são colocados em uma fila e não interferem nos itens de lote de entrada regulares do SQS, podemos avançar para o próximo estágio: o mecanismo de redirecionamento e autocorreção do DLQ.
Redirecionamento da fila de letras mortas
O DLQ contém itens de lote com falha; ótimo! Agora precisamos decidir o que fazer com eles.
Se você se lembra, nossa função Lambda contém a lógica de negócios para manipular itens em lote.
O ideal é manter sua lógica de negócios naquele Lambda em vez de copiá-la para outro Lambda que o DLQ acionará com os itens de lote com falha.
Felizmente, em 6 de junho de 2023, a AWS lançou uma nova API de redirecionamento que resolve esse dilema.
mova programaticamente mensagens do DLQ para sua fila original ou para um destino de fila personalizado, para tentar processá-las novamente. - Documentação da AWS
O design que sugiro é criar um mecanismo de autocura. Usaremos uma tarefa do agendador EventBridge que dispara uma função Lambda que é executada uma vez por dia (ou quantas vezes você achar necessário). A função Lambda pega os itens de lote com falha do DLQ e os redireciona, ou seja, os envia de volta ao SQS original, onde serão enviados para a função Lambda de processamento em lote e tentados novamente.
Você pode usar este design em qualquer serviço que utilize o padrão SQS --> Lambda.
Se você deseja saber mais sobre as tarefas do agendador do EventBridge, leia minha postagem no blog aqui .
Aqui está o diagrama de projeto do redrive:
Como a repetição ocorre ocasionalmente, pode ser seguro assumir que o processamento em lote pode ter sucesso em tentativas posteriores.
No entanto, em caso de falhas contínuas, você deve ser capaz de monitorar as falhas e corrigi-las ou adicionar código na função SQS Lambda que as ignorou para que elas não sejam marcadas como falhas novamente. Você pode aprender mais sobre observabilidade em meu post aqui .
Agora que entendemos o design, vamos escrever o CDK e redirecionar o código da função Lambda.
Código CDK
Vamos escrever o código de infraestrutura que define nosso SQS, o destino Lambda e a fila de mensagens mortas. O SQS enviará itens de lote com novas tentativas com falha para o DLQ automaticamente quando as tentativas de nova tentativa terminarem em vão.
Expandiremos o código CDK do primeiro artigo e adicionaremos o DLQ e a tarefa agendada para o recurso de redirecionamento.
Nas linhas 12-18, definimos o DLQ. Habilitamos a criptografia gerenciada pelo SQS para que tivéssemos criptografia em repouso (segurança em primeiro lugar!).
Nas linhas 24 a 27, conectamos o DLQ ao SQS e definimos a contagem máxima de recebimento.
A contagem máxima de recebimento é definida como:
O número máximo de vezes que uma mensagem pode ser recebida pelos consumidores. Quando esse valor for excedido para uma mensagem, a mensagem será automaticamente enviada para a Dead Letter Queue.
Você pode ler mais sobre isso aqui .
Nas linhas 35-36, definimos uma nova variável de ambiente para a função redrive Lambda. Ela precisa dos ARNs DLQ e SQS para chamar a API redrive.
Nas linhas 41-74, definimos uma tarefa do agendador EventBridge que aciona uma função Lambda todos os dias às 23h, horário de Israel, entre domingo e quinta-feira. O código da função segue abaixo. O Lambda chamará o AWS SDK (boto3) para recuperar mensagens do DLQ para o SQS de origem. Damos à tarefa as permissões necessárias para acionar a função.
Você pode encontrar todos os exemplos de código CDK aqui .
Função Lambda Redrive
Você pode encontrar o código CDK que define a função redrive aqui na função '_create_dlq_lambda'.
Observe que você deve definir as permissões de função com o mínimo de privilégios, conforme sugerido no guia do desenvolvedor do SQS, e não conforme apresentado no exemplo.
Agora, vamos dar uma olhada no código do manipulador de funções:
Na linha 12, usamos a biblioteca aws_lambda_env_modeler (que eu mantenho) para analisar as variáveis de ambiente da função para obter os ARNs SQS e DLQ. Se você quiser saber por que validar variáveis de ambiente é vital, confira meu post .
Nas linhas 19 a 27, chamamos a API de unidade de API 'start_message_move_task' e registramos quaisquer exceções.
É isso. Bem direto. Assim que a tarefa de redrive for concluída, os itens com falha aparecerão no SQS e serão enviados para a função Lambda de processamento em lote do SQS para serem processados novamente e, com sorte, com sucesso dessa vez.
Considerações Finais
Processamento em lote com SQS e Lambda é um dos casos de uso mais básicos de qualquer aplicativo serverless. No entanto, é fácil errar.
Ao longo de três artigos, temos:
Definiu as melhores práticas para processar os itens em lote de forma simples
Implementada nova tentativa no nível do Lambda por item com 'tenacidade'.
Implementada nova tentativa no nível SQS
Implementou um DLQ
Implementou um recurso de redrive de autocorreção com o agendador EventBridge.
Comments