Neste post, você obterá conhecimento prático de como o SQS FIFO funciona de uma perspectiva detalhada. Você aprenderá a atingir o maior throughput possível e configurá-lo corretamente com exemplos de código TypeScript do CDK.
Introdução do escritor convidado
Marcos Henrique é um engenheiro sênior de nuvem (também conhecido como AWS Janitor) na Welbe Care e um Serverless AWS Community Builder. Com mais de dez anos em tecnologia, ele é apaixonado por tecnologias de nuvem e as utiliza para resolver problemas complexos e aprimorar a escalabilidade e a eficiência do sistema.
Você pode seguir Marcos em sua página do LinkedIn .
Índice
Breve introdução ao SQS
O Amazon SQS (Simple Queue Service) não é "simples" em termos de como você pode desacoplar os componentes de um aplicativo de nuvem ou como ele pode ser dimensionado. O SQS oferece um sistema de fila distribuída seguro, altamente disponível e confiável para armazenamento e processamento de mensagens assíncronas. Ele fornece ciclos de vida de mensagens configuráveis e entrega garantida por meio de armazenamento redundante em várias zonas de disponibilidade.
Embora o SQS ofereça muitos recursos benéficos, ele gera alguns desafios devido a duas limitações inerentes:
Nenhuma ordem garantida : as mensagens podem chegar fora de ordem, exigindo que os desenvolvedores gerenciem a ordem.
Possíveis duplicatas : as mensagens podem ser entregues mais de uma vez, necessitando de tratamento de idempotência .
Para superar essas limitações, podemos usar outro tipo de SQS: o SQS FIFO (first in, first out) .
FIFO SQS
As filas FIFO (First-In-First-Out) têm todos os recursos das filas padrão. Elas são projetadas para aprimorar mensagens entre aplicativos quando a ordem das operações e eventos é crítica ou onde duplicatas não podem ser toleradas.
O FIFO permite manipular mensagens como sua linha de cafeteria favorita, respeitando a ordem das mensagens e removendo duplicações de mensagens.
Como tudo o mais, não é um recurso de plug-in e tem limitações/cotas , como ser mais lento e mais caro do que as filas regulares do SQS.
Enviando e recebendo mensagens
Ao trabalhar com filas FIFO SQS, é essencial entender o Message Deduplication ID e o Message Group ID. O Message Deduplication ID é um token que impede o SQS de enviar a mesma mensagem várias vezes. Se uma mensagem com um ID de deduplicação específico for enviada com sucesso, outras mensagens com o mesmo ID serão aceitas, mas não entregues novamente dentro de uma janela de 5 minutos. É assim que o SQS FIFO remove a limitação de mensagens duplicadas.
O Message Group ID marca uma mensagem pertencente a um grupo específico. Mensagens no mesmo grupo são processadas uma de cada vez em ordem, mas mensagens de grupos diferentes podem ser processadas fora de ordem. É assim que o SQS FIFO remove a limitação de mensagens fora de ordem.
Conforme exibido na imagem abaixo, se você disparar muitas mensagens com IDs exclusivos para uma fila FIFO, o Amazon SQS as alinhará e as manipulará em ordem. Mensagens com o mesmo ID de grupo são armazenadas e processadas conforme chegam. Para manter as coisas organizadas, cada remetente deve usar um ID de grupo exclusivo. Lembre-se, se você não marcar suas mensagens com um ID de grupo, o Amazon SQS não jogará bola.
Tenha em mente que você não pode solicitar mensagens diretamente com um ID de grupo específico no destinatário da mensagem.
Quando você puxa mensagens de uma fila FIFO com vários IDs de grupo, o Amazon SQS tenta lhe dar o máximo de mensagens do mesmo grupo para que outros consumidores possam pegar grupos diferentes. Depois que você recebe uma mensagem de um grupo, apenas mais mensagens daquele grupo chegam até você.
Você pode receber muitas mensagens de uma vez, mantendo a ordem FIFO delas, mas se não houver o suficiente de um grupo, você receberá algumas de outro, como visto na imagem abaixo, onde o Consumer 1 recebe mensagens dos grupos A e B no segundo lote. Os lotes têm um tamanho máximo de 10 mensagens.
Limitações
Antes de começar, é importante ter em mente que não existe solução mágica, então precisamos abordar duas limitações antes de implementar.
Desempenho
A primeira limitação é o desempenho. O suporte à entrega de mensagens exatamente uma vez e em ordem pode impactar significativamente o desempenho da fila FIFO, potencialmente criando um gargalo em seu aplicativo. As filas FIFO têm uma taxa de transferência menor do que as filas padrão, com um limite padrão de 300 transações por segundo (TPS). No entanto, o agrupamento pode aumentar esse limite para 3.000 TPS.
Você deve estar sempre ciente das limitações de desempenho para lidar com elas de forma eficaz. Por exemplo, crie o ID do grupo de mensagens com cuidado, pois as mensagens com o mesmo ID do grupo de mensagens serão retornadas em ordem. Embora esse seja o comportamento pretendido para uma fila FIFO, lembre-se de que somente depois que uma mensagem for removida da fila a mensagem seguinte com o mesmo ID do grupo de mensagens será retornada.
Desduplicação de mensagens
A segunda limitação é a desduplicação de mensagens. A desduplicação baseada em conteúdo é possível com filas FIFO, que removem mensagens duplicadas em 5 minutos. Esse intervalo de tempo não pode ser alterado, então os aplicativos que dependem da desduplicação de mensagens devem estar cientes dessa restrição.
Cenário do mundo real de alto rendimento
Estávamos implementando um sistema de mensagens para informar nossos clientes sobre resultados de exames laboratoriais, então precisávamos que essas mensagens seguissem uma cronologia específica. Imagine receber uma série de mensagens sem contexto cronológico; seria uma bagunça. Portanto, o SQS não seria o ideal para o nosso caso, então optamos pelo FIFO. No entanto, nem tudo foi tranquilo.
Como temos milhares de clientes e milhares de mensagens para cada cliente, precisávamos de algo rápido. Dadas as limitações de desempenho mencionadas anteriormente, tivemos que repensar toda a nossa configuração. Como o FIFO pode causar um gargalo , tivemos que encontrar uma maneira de torná-lo escalável. É aí que entra o High throughput para filas FIFO no Amazon SQS .
FIFO SQS Alto rendimento para o resgate
Primeiro, isso salvou nosso dia e nos ajudou com nosso grande volume de mensagens. Como não existe uma solução mágica, precisamos estar sempre cientes das limitações de nossas ferramentas.
As filas FIFO de alto rendimento no Amazon SQS manipulam muitas mensagens enquanto mantêm ordens estritas, o que é perfeito para processamento de pedidos de alta demanda. No entanto, elas são necessárias somente se a ordem das mensagens for crucial ou o volume de mensagens for baixo. As filas padrão são mais simples e baratas para mensagens de pequena escala ou pouco frequentes.
Para obter detalhes sobre cotas de mensagens e estratégias de distribuição de dados, consulte Cotas de serviço do Amazon SQS .
Partições e Distribuição de Dados
O Amazon SQS armazena dados de fila FIFO em partições , replicadas automaticamente em várias zonas de disponibilidade dentro de uma região da AWS. Você não gerencia essas partições, o Amazon SQS faz isso por você.
Para filas FIFO, o Amazon SQS ajusta o número de partições com base na demanda:
Se a taxa de solicitação for alta, mais partições serão adicionadas à cota regional.
Se a utilização for baixa, as partições podem ser reduzidas.
Esse gerenciamento acontece em segundo plano, mantendo sempre sua fila e mensagens disponíveis.
Ao adicionar uma mensagem a uma fila FIFO, o Amazon SQS usa o ID do grupo de mensagens com uma função hash para determinar qual partição armazena a mensagem. As mensagens são armazenadas na ordem em que chegam, com sua localização baseada no valor hash do ID do grupo de mensagens.
Aumentar o número de grupos de mensagens aumentará potencialmente o número de partições e a taxa de transferência em filas FIFO SQS de alta taxa de transferência.
Exemplo de codificação
Vamos configurar nossa fila FIFO SQS com alto rendimento habilitado usando CDK e Typescript.
Primeiro, definiremos nossa fila e então escreveremos o código para o produtor da mensagem:
Linha 10: Devemos fornecer o sufixo ".fifo"; caso contrário, ele falhará quando você implantar.
Linha 11: Este parâmetro deve ser verdadeiro para configurar nosso fifo.
Linha 12 : Aqui, você configurará seu alto rendimento e especificará se a desduplicação de mensagens ocorre no nível do grupo de mensagens ou da fila. Por exemplo, se você precisa ter várias desduplicações com base em cada grupo de mensagens, é aqui que a mágica acontece. Caso contrário, você pode encontrar alguns problemas, pois o padrão é definido para a fila inteira.
Linha 13: Especifica se a cota de throughput da fila FIFO se aplica à fila inteira ou por grupo de mensagens. Defina isso como PER_MESSAGE_GROUP_ID, a configuração necessária para usar alto throughput para filas FIFO
Linha 14 : Isso foi definido como falso porque neste exemplo não estamos usando um conteúdo de mensagem bem definido. No entanto, se for o seu caso, você pode defini-lo como verdadeiro.
Agora, vamos produzir mensagens:
Linha 11 : Esta linha configura atributos de mensagem (Título e Tipo) para metadados específicos associados ao conteúdo da mensagem.
Linha 21 : Especifica um MessageDeduplicationId exclusivo para garantir que mensagens duplicadas sejam corretamente identificadas e processadas na fila FIFO.
Linha 22 : Define um MessageGroupId para agrupar mensagens relacionadas (resultados de exames de sangue) que devem permanecer em ordem durante o processamento.
Dicas e truques
Agora que entendemos os fundamentos, vamos explorar algumas dicas e truques para escrever código FIFO SQS que lida com alto rendimento.
Produção de mensagens e desduplicação
Vamos revisar algumas considerações antes de enviar uma mensagem para uma fila FIFO SQS de alto rendimento.
Para configurar a deduplicação, você pode habilitar a deduplicação baseada em conteúdo, que usa um hash SHA-256 do corpo da mensagem. Esse método pode ser complicado e pode não funcionar como esperado se houver uma pequena diferença, como um espaço extra, na mensagem.
Como alternativa, você mesmo pode fornecer um ID de desduplicação de mensagem. Isso é especialmente útil se você estiver trabalhando com um provedor de chat de mensagem como o WhatsApp, onde enviar mensagens diferentes para a mesma pessoa geralmente requer um ID exclusivo para cada ID de grupo de mensagem.
No primeiro caso de uso, se seu aplicativo enviar corpos de mensagem idênticos e fornecer um ID de desduplicação exclusivo para cada mensagem, você deverá escolher com cuidado .
Por outro lado, se seu aplicativo enviar corpos de mensagens exclusivos, habilite a desduplicação baseada em conteúdo .
Por fim, nenhuma alteração é necessária para os consumidores, mas se o processamento demorar muito, adicione um ID de tentativa de solicitação de recebimento a cada ação ReceiveMessage para lidar com novas tentativas e evitar pausas na fila devido a tentativas malsucedidas.
Preferir APIs em lote
Como o FIFO é mais lento que o SQS normal, devemos considerar lotes ao receber mensagens.
O tamanho máximo de lote para filas FIFO é 10 registros . O processamento usando esse limite aumenta significativamente o desempenho, quase 10 vezes melhor do que definir a fila FIFO do SQS para batchSize: 1 .
Reduzir Custos
O comportamento padrão do SQS FIFO é desduplicar mensagens em toda a fila.
Se você quiser desduplicar mensagens dentro de cada ID de grupo de mensagens, você deve habilitar o modo High Throughput, o que pode ser caro. Para economizar custos, você pode obter um resultado semelhante adicionando um prefixo ao ID de desduplicação de mensagens ao enviar mensagens com base no ID de grupo de mensagens, lembre-se de que cada grupo deve ser tratado como uma partição, então é essencial considerar suas cotas adequadamente.
Vamos dar uma olhada no exemplo de código abaixo:
Nas linhas 17 e 18 , você pode ver onde a alteração está definida. Isso nos permite obter deduplicação por ID de grupo de mensagens sem incorrer em custos adicionais. Por exemplo, suponha que você tenha diferentes IDs de grupo de mensagens para vários tipos de comunicações, como WhatsApp, e-mails e SMS.
Ao atribuir um ID de grupo de mensagens exclusivo a cada tipo de comunicação, você garante que as mensagens dentro do mesmo grupo sejam processadas em ordem e sem duplicação. Essa abordagem ajuda a organizar as mensagens de forma lógica e eficiente, evitando duplicatas dentro de cada grupo e mantendo a sequência de entrega de mensagens sem a necessidade de mecanismos de desduplicação adicionais, o que poderia incorrer em custos extras.
Falhas e Tentativas
Para gerenciar mensagens com falha e de nova tentativa, é importante garantir que elas sejam repetidas sem preocupação com a ordem ou a criação de novas mensagens. Se uma mensagem não for enviada, o produtor deve reenviá-la usando o mesmo ID de deduplicação.
Depois que você receber uma mensagem com um ID de grupo, somente mais mensagens daquele grupo chegarão até você depois que você lidar com elas, ou elas se tornarão visíveis novamente. Para uma compreensão abrangente de novas tentativas e falhas, incluindo os conceitos de filas de letras mortas, consulte estes guias detalhados:
Dicas gerais do SQS
Por fim, recomendo fortemente que você confira o artigo sobre as melhores práticas do SQS da AWS.
Conclusão
Como tudo na vida, precisamos analisar nosso caso, pensar nas melhores práticas e ser céticos quanto à possibilidade de as coisas funcionarem na primeira vez; sempre precisamos considerar o pior cenário ao projetar uma solução.
Devemos ser sempre frugais porque isso é uma qualidade, não um defeito do caso de desenvolvimento. Precisamos ter uma mente alinhada com a necessidade de escala hoje. Tudo é escalável, e tudo pode ser consumido massivamente, então precisamos que nossos sistemas tenham cada vez mais flexibilidade, mas sem negligenciar a resiliência e a segurança de nossas aplicações; por isso, decidi condensar tudo o que aprendi com trabalho duro debruçando-me sobre pilhas de artigos e documentação, este post foi criado com muito suor e lágrimas.
Boas filas e que suas mensagens sempre cheguem na hora certa (e na ordem)!
Comments