aws-sqs
Visão geral
A biblioteca que usamos faz uma abstração em cima da biblioteca do RabbitMQ usada em cada Stack. O uso dela visa trazer alguns recursos que geralmente as bibliotecas disponíveis não fornecem. Sendo os principais:
Reprocessamento de mensagens que tiveram erro ao processar com delay;
Reconexão automática com o servidor RabbitMQ e registro automático dos consumidores que estavam conectados antes da perda de conexão.
A ideia é que cada stack usada na empresa tenha sua abstração para seguir o fluxo apresentado neste documento. Atualmente temos as bibliotecas desenvolvidas em:
Node.js: hoje está dentro do shippon-monorepo, como uma lib do projeto. No entanto, ela pode ser exportada com pequeno esforço e colocada em um pacote autônomo. (inclusive a api-elk a usa, mesmo estando fora do monorepo) Golang: pacote go-rabbitmq
Vale ressaltar que cada implementação deve ter sua documentação no readme, explicando seu uso. Além disso, podem haver diferenças sutis entre as implementações de cada stack, devido a conceitos e paradigmas que cada stack pode ter, por isso é importante consultar as docs de cada uma delas além deste documento. Além disso, contamos com todos para mantê-las atualizadas.
- Você pode e deve propor e ajudar a manter/implementar melhorias para o fluxo apresentado aqui, bem como para as implementações das abstrações dele em cada stack.
Namespaces
Utilizamos um padrão de namespaces, para conseguir separar as exchanges e queues de acordo com o escopo de aplicação. Hoje, possuímos 3 namespaces.
fr (plataforma Frete Rápido)
shippon (plataforma Shippon)
integrations (novo sistema de integrações que no futuro deve ser usado pela Shippon e Frete Rápido)
A nomenclatura das exchanges e queues utilizam um dos namespaces apresentados como prefixo, como veremos a seguir.
Exchanges
A nomenclatura das exchanges segue o padrão apresentado abaixo:
-> namespace.exchange-type.exchange-flow
namespace: separação de escopo de aplicação apresentado anteriormente
exchange-type: o tipo de exchange usada no RabbitMQ (usamos somente direct até o momento)
exchange-flow: papel que a exchange representa dentro do fluxo de trabalho que usamos, veja as possíveis opções abaixo:
sem fluxo definido (nesse caso, trata-se da exchange principal)
retry
requeue
dead
Definição de fluxo das Exchanges
sem fluxo (exchange principal): aqui não temos nenhuma regra específica, trata-se da exchange de entrada para as mensagens, ela deve direcioná-las para a fila onde estão os consumidores.
retry: essa exchange é usada internamente pelos consumidores para republicar uma mensagem que teve erro no processamento, nesse caso, a exchange irá direcionar a mensagem para uma fila de espera (wait), para ser reprocessada no futuro
requeue: quando uma mensagem chega na fila de espera (wait), depois de um certo período ela expira, quando isso acontece, essa exchange cuida de direcioná-la de volta para a fila principal, para uma nova tentativa de processamento pelo consumidor. (esse processo se repete, até que o limite de tentativas definido na aplicação seja atingido)
dead: como mencionado na exchange anterior, existe um limite de tentativas de reprocessar uma mensagem, quando esse limite é atingido, internamente o consumidor irá republicar a mensagem, mas dessa vez apontando para essa exchange, que irá direcioná-la para uma fila de mensagens “mortas” (dead), ou seja, as mensagens que tiveram o limite de tentativas de reprocessamento excedido, ficam armazenadas nessa fila para análise manual do time de engenharia.
O conjunto de exchanges é criado uma única vez para cada namespace, depois disso, para as novas queues que surgem, são adicionados bindings entre exchange X queue. Abaixo, temos um exemplo de exchanges para um namespace:
fr.direct
fr.direct.retry (interna)
fr.direct.requeue (interna)
fr.direct.dead (interna)
Queues
A nomenclatura das queues segue o padrão apresentado abaixo:
-> namespace.queue-name.queue-flow
namespace: separação de escopo de aplicação apresentado anteriormente
queue-name: o nome da queue deve ser customizado de acordo com a necessidade da aplicação, por convenção usamos as separações com hifens. ex.: nome-da-fila
exchange-flow: papel que a queue representa dentro do fluxo de trabalho que usamos, veja as possíveis opções abaixo:
sem fluxo definido (nesse caso, trata-se da queue principal)
wait
dead
Definição de fluxo das Queues
sem fluxo (queue principal): a queue principal é onde os consumidores se inscrevem para receber as mensagens. Quando uma mensagem não pôde ser processada pelo consumidor, ele internamente irá republicá-la na exchange retry ou exchange dead, a escolha da exchange depende da quantidade de tentativas de processamento da mensagem, sendo que cada aplicação pode ter sua própria definição. De acordo com a exchange escolhida, a mensagem pode ser enviada para uma das queues que veremos a seguir.
wait: as mensagens que chegarem aqui, permanecerão na fila por X tempo, definido pelo consumidor que a publicou, após esse tempo, essa mensagem expira e será automaticamente removida da queue e recebida pela exchange requeue que irá direcioná-la novamente para a queue principal.
dead: esse é o destino final das mensagens que não puderem ser processadas após o limite de tentativas especificado na aplicação. O intuito de mantê-las aqui, é para que o time de engenharia possa analisá-las e entender se existe alguma melhoria que possa ser feita na aplicação para conseguir processar casos semelhantes no futuro. Além disso, ela pode servir como um ponto de segurança para mensagens que não foram processadas, por algum erro inesperado na aplicação.
Observe que os consumidores devem estar inscritos somente na queue principal, ou seja, aquela que não possui nenhum fluxo diferente definido. As demais queues, são usadas internamente pela biblioteca para garantir o fluxo de tentativas de reprocessamento de mensagens com delay.
Veja abaixo um exemplo de conjunto de filas que uma aplicação deve ter para usar o fluxo que vimos aqui:
fr.queue-name
fr.queue-name.wait (interna)
fr.queue-name.dead (interna)
Routing Keys
CONTINUAR AQUI, OLHAR EXCHANGES PARA LEMBRAR SOBRE COMO ESTÁ A PADRONIZAÇÃO
Fluxograma do fluxo de trabalho descrito no documento
Pode ser acessado através do desse endereço, com a senha: fr@developers
