Você está na página 1de 57

Universidade Federal de Pernambuco

Centro de Informática
Bacharelado em Ciência da Computação

Proposta de Arquitetura para Monitoramento e


Reprocessamento de Mensagens de Dead Letter Queue do
Amazon Simple Queue Service

Trabalho de Conclusão de Curso de Graduação


por

Edjan Sobral Verı́ssimo Michiles


Orientador: Prof. Vinı́cius Cardoso Garcia

Recife, Dezembro / 2021


Edjan Sobral Verı́ssimo Michiles

Proposta de Arquitetura para Monitoramento e Reprocessamento de


Mensagens de Dead Letter Queue do Amazon Simple Queue Service

Monografia apresentada ao Bacharelado em


Ciência da Computação, como requisito
parcial para a obtenção do Tı́tulo de
Bacharel em Ciência da Computação, Centro
de Informática.

Orientador: Prof. Vinı́cius Cardoso Garcia

Recife
2021
Agradecimentos

Estudar Ciência da Computação na UFPE é um sonho


de criança, por isso gostaria de agradecer a Deus pela
oportunidade, aos meus pais que sempre me apoiaram,
especialmente o meu pai José Verı́ssimo que sempre
pegou muito no meu pé. Gostaria de agradecer também
aos meus colegas de curso, aos professores, à minha
namorada, Adrielly Camila, que me apoiou bastante
durante o desenvolvimento do TCC, a Lucas Valença que
me ajudou bastante durante toda a faculdade, viramos
várias noites fazendo projeto juntos, a Gustavo Lopes
pelas várias dicas para o TCC, aos meus companheiros de
trabalho por onde passei, a Loft por ter sido flexı́vel e ao
presidente Lula por tornar as universidades federais mais
acessı́veis para pessoas que, assim como eu, possuem
origem humilde.
RESUMO

Este trabalho tem por objetivo propor um modelo de arquitetura de software para mo-
nitoramento e reprocessamento de mensagens do Amazon Simple Queue Service (SQS)
utilizando o Datadog juntamente com Terraform para monitoramento e Github Actions
como ferramenta de reprocessamento de mensagens manual. A princı́pio, serão apresen-
tados os conceitos de filas tradicionais e dead letter queues (DLQs). Em seguida, serão
levantados alguns problemas recorrentes no reprocessamento de mensagens. Após isso,
serão apresentados alguns desafios encontrados no dia a dia de pessoas engenheiras de
software responsáveis por alguma aplicação que faz o uso de processamento assı́ncrono
através de filas e como os conceitos de monitoramento e observabilidade ajudam a miti-
gar problemas de maneira rápida, reduzindo os impactos sentidos pelos usuários finais.
Então serão introduzidas as ferramentas que iremos utilizar e a proposta de arquitetura,
detalhando o passo a passo de sua implementação. Por fim, os resultados que validam a
arquitetura proposta e considerações finais com limitações serão apresentados.

Palavras-chave: Monitoramento, Observabilidade, Dead Letter Queue, Reprocessamento


de Mensagens, Filas, Processamento Assı́ncrono.
ABSTRACT

This work will describe an architecture proposal for monitoring and reprocessing messages
from the Amazon Simple Queue Service (SQS) using Datadog and Terraform as monito-
ring tools and GitHub Actions to dispatch manually message reprocessing. At first, the
usual queues and dead letter queues (DLQs) concepts will be presented.Afterward, rele-
vant message reprocessing issues will be discussed. Such issues are often part of the daily
routine of software engineers responsible for applications that use asynchronous proces-
sing. This work will also discuss how the concepts of monitoring and observability can be
employed to mitigate the previously-mentioned issues and improve user experience. Then,
this work will introduce the necessary tools and describe the step-by-step implementation
of the proposed architecture. Finally, the results that validate the proposed architecture
and final considerations will be showed.

Keywords: Monitoring, Observability, Dead Letter Queue, Messages Reprocessing, Queues,


Asynchronous Processing.
LISTA DE FIGURAS

Figura 1 Exemplo de sistema utilizando EDA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13


Figura 2 Fila de Mensagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Figura 3 Arquitetura proposta.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Figura 4 Pesquisa por SQS no console da AWS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Figura 5 Criando fila no SQS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Figura 6 Criando fila no SQS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Figura 7 Exibição da fila SQS criada no modo FIFO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Figura 8 Exibição da fila SQS que será utilizada como DLQ. . . . . . . . . . . . . . . . . . . . . . . . . . 26
Figura 9 Configurando uma DLQ para a fila principal. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Figura 10 Fila principal possui uma DLQ configurada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Figura 11 Menu da conta da AWS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Figura 12 Gerando uma access key no AWS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Figura 13 Mensagem de sucesso do produtor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Figura 14 Mensagens disponı́veis na fila principal. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Figura 15 Conteúdo da mensagem disponı́vel na fila principal. . . . . . . . . . . . . . . . . . . . . . . . . 31
Figura 16 Resultado do consumo da fila. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Figura 17 Acessando página de configurações pessoais no Datadog. . . . . . . . . . . . . . . . . . . . 34
Figura 18 Criando uma nova application key no Datadog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Figura 19 Procurando integração com AWS no Datadog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Figura 20 Acesso ao SQS habilitado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Figura 21 Adicionar nova conta da AWS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Figura 22 Informar chave do Datadog na AWS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Figura 23 Criando stack na AWS para o Datadog.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Figura 24 Preencher informações da conta AWS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Figura 25 Métrica de número de mensagens recebidas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Figura 26 Acessando API key do Datadog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Figura 27 Acessando application key do Datadog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Figura 28 Estrutura dos arquivos Terraform no repositório.. . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Figura 29 Alerta criado no Terraform. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Figura 30 Email recebido do Datadog alertando sobre erro.. . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Figura 31 Alerta no Datadog com status de erro. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Figura 32 Trecho de código da aplicação responsável por mover mensagens de uma
fila para outra. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Figura 33 Interface para acionar o workflow no Github. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Figura 34 Acionando workflow no Github . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Figura 35 Resultado do workflow de reprocessar mensagens. . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Figura 36 Rodando consumidor novamente após as mensagens serem movidas da
DLQ para a fila principal. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Figura 37 Aviso do Datadog de recuperação do estado da DLQ . . . . . . . . . . . . . . . . . . . . . . . 53
LISTA DE SIGLAS

DLQ Dead Letter Queue


AWS Amazon Web Services
EDA Event-Driven Architecture
FIFO First-In-First-Out
TTL Time To Live
JSON JavaScript Object Notation
CPU Central Processing Unit
SQS Simple Queue Service
DNS Domain Name System
API Application Programming Interface
SUMÁRIO

1 INTRODUÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2 CONCEITOS BÁSICOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1 Conceitos de Arquitetura de Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Medição de DevOps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3 VISÃO GERAL DA ARQUITETURA PROPOSTA . . . . . . . . . . . . . . . . . 18


3.1 Ferramentas Utilizadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.2 Amazon SQS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 Datadog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4 Terraform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.5 Github Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.6 Utilização dos Componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.7 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4 PROPOSTA EM AÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.1 Criando a Base do Projeto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.1.1 Criando a Fila no Amazon SQS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.1.2 Configurando DLQ para a Fila. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.1.3 Criando Credenciais na AWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.1.4 Criando Produtor para a Fila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1.5 Criando Consumidor para a Fila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.2 Criando o Projeto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2.1 Integrando Datadog a AWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.2.2 Criando Alerta para a DLQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2.3 Criando Github Action para Reprocessar Mensagens . . . . . . . . . . . . . . . . 46

5 CONCLUSÃO E TRABALHOS FUTUROS . . . . . . . . . . . . . . . . . . . . . . . . . . . 54


9

1 INTRODUÇÃO

Com o passar dos tempos, a difusão da internet e o crescente número de usuários,


surgem cada vez mais preocupações com o desempenho e a escalabilidade das aplicações.
Ao falar sobre escalabilidade estamos falando sobre como dividimos e conquistamos as
tarefas para manter a aplicação estável enquanto o número de requisições aumenta. Por
desempenho se pensa sobre quão eficientemente essas tarefas são executadas [1].
Por conta disso, uma arquitetura baseada em eventos (ou assincronamente dis-
tribuı́da) é bastante popular para construir sistemas altamente escaláveis e com alto de-
sempenho [2].
Numa arquitetura orientada a eventos, existem dois atores principais: consumidor
e produtor. Os produtores são os responsáveis por produzir eventos em forma de men-
sagem. Os consumidores ouvem as mensagens através de canais [2]. Estes canais podem
ser: Filas de Mensagens, Tópicos de Mensagens, ou os dois, de acordo com [3].
Cada mensagem em uma fila só é processada uma vez, por um único consumidor.
Entretanto, muitos produtores e consumidores podem utilizar uma mesma fila para reali-
zar a comunicação entre si [4]. Quando um erro ocorre durante o processamento de uma
mensagem da fila, automaticamente as pessoas desenvolvedoras já pensam numa lógica
de retry automático. Isto é muito eficiente quando o erro que aconteceu foi por conta
de um timeout, por exemplo. Porém, em muitas ocasiões, não importa quantas vezes a
mensagem seja reprocessada, ela sempre irá falhar. Por conta disso, é interessante analisar
esta mensagem de maneira isolada, para que o problema possa ser identificado e corrigido.
Para tal, uma abordagem interessante é a de mover esta mensagem para uma fila especial,
chamada de Dead Letter Queue (DLQ) [5].
Dado que a mensagem problemática foi movida para uma fila especial para ser
analisada, é importante que as pessoas engenheiras de software responsáveis pela aplicação
sejam notificadas ou seja criado um sistema para receber as mensagens da DLQ, caso
contrário a mensagem problemática cairá no esquecimento. Este projeto não não o intuito
de automatizar esse reprocessamento de mensagens e sim de fazê-lo de maneira manual
[5]. Para isso, serão necessários dois conceitos do mundo DevOps: observabilidade e
monitoramento.
Observabilidade significa quão bem uma pessoa desenvolvedora consegue saber a
10

saúde dos seus sistemas. Para tal, existem três pilares essenciais: logs, métricas e trace
das aplicações. O Monitoramento de uma aplicação tem como objetivo alertar quando
foi observado algo fora do normal. Portanto, só é possı́vel monitorar uma aplicação que é
observável, conforme descrito em [6].
Este trabalho propõe uma arquitetura que propicia o monitoramento de DLQs
do Amazon Simple Queue Service e permite que as mensagens sejam reprocessadas via
Github Actions após as devidas análises serem realizadas. O principal objetivo deste
projeto é resolver alguns desafios enfrentados no dia a dia de pessoas desenvolvedoras
responsáveis por sistemas que utilizam arquitetura baseada em eventos com uma DLQ.
Este projeto foca mais especificamente no caso de ser necessário analisar cada uma das
mensagens que não foram processadas corretamente para que, após as devidas correções,
quando necessárias, o reprocessamento das mensagens seja feito de forma manual. Isso
se dá no cenário onde a perda de uma única mensagem pode ser muito significativa para
a empresa. São casos em que normalmente uma mensagem possui um valor de negócio,
como por exemplo o agendamento de uma visita a um apartamento.
Para alcançar esse objetivo, primeiro serão apresentados os conceitos necessários
ao entendimento do projeto. Após isso, as ferramentas utilizadas para alcançar o objetivo
deste trabalho serão apresentadas e brevemente introduzidas. Em seguida, será demons-
trada a implementação da arquitetura proposta e, ao final, serão discutidos os resultados
do projeto.
11

2 CONCEITOS BÁSICOS

Neste capı́tulo serão apresentados e discutidos os principais conceitos necessários


para o entendimento do desenvolvimento do projeto.

2.1 Conceitos de Arquitetura de Software

Esta seção explica brevemente os conceitos de arquitetura de microsserviços e ar-


quitetura baseada em eventos.

Arquitetura de Microsserviços

Para abordarm o conceito de arquitetura de microsserviços, é necessário entender


o que é um microsserviço.
Microsserviços são serviços pequenos e focados em um contexto de negócio bem
especificado, para que todas as funcionalidades relacionadas a esse contexto fiquem defi-
nidas dentro deste serviço, tal qual como se fosse um pedaço de código como definido pelo
princı́pio da responsabilidade única [7].
Existem duas caracterı́sticas que são essenciais para um microsserviço, além dele ser
pequeno e possuir um contexto delimitado. Essas caracterı́sticas são o fraco acoplamento
e uma alta coesão. O fraco acoplamento significa que os serviços são independentes.
Ou seja, é possı́vel realizar uma alteração em cada um deles de maneira individual e isso
não deve impactar outros serviços. Por alta coesão se entende que quando se deseja
alterar um comportamento, essa alteração deve ser feita em um único lugar: no serviço
que lida com esse contexto [8].
Ao se utilizar microsserviços, diversos benefı́cios podem ser elencados. Vamos
descrever alguns deles, de acordo com [7].
Variedade de tecnologias - pelo fato de cada serviço ser independente, fica a
critério do time escolher a tecnologia a ser utilizada de acordo com a necessidade.
Escalabilidade - quando um serviço precisa de mais recurso, é possı́vel escalar
ele sem se preocupar em escalar a aplicação inteira.
Facilidade para fazer deploy - como cada serviço é independente, é mais fácil
criar funcionalidades novas e ajustar bugs. Quando algum problema ocorre, é mais fácil
reverter o código defeituoso pois está isolado a um único sistema. Isso também significa
12

que os deploys são mais rápidos, pois é necessário rodar um conjunto menor de testes e
compilar um trecho menor de código.
Times pequenos e focados - ao falar de serviços com bases de código pequenas,
torna-se possı́vel ter times menores e mais focados em seus contextos.
Pela arquitetura de microsserviços utilizar esses tipos de serviços, esses benefı́cios
são herdados, como por exemplo a redução de débitos técnicos, o aumento da produtivi-
dade dos desenvolvedores, uma maior possibilidade para escalar, uma maior eficiência de
testes, entre outros, conforme citado em [9].
A utilização de microsserviços traz consigo diversas vantagens, como citado ante-
riormente. Porém também é necessário ficar atento a novos desafios que irão surgir. De
acordo com [9], podemos elencar quatro desses principais desafios.
Comunicação entre times - o fato de haver times menores e mais focados
também implica que haverá uma quantidade maior de times que são isolados de acordo
com o seu contexto e independentes. Isso significa que os times precisam atuar mais
próximos uns dos outros e com uma comunicação muito bem alinhada, o que não é uma
tarefa fácil.
Variedade técnica - do mesmo jeito que este ponto pode ser um aliado dos times
no quesito de liberdade e independência, ele também pode ser um grande desafio. Ter
diferentes times atuando com diferentes linguagens, bibliotecas, tecnologias, ferramentas,
entre outros, se torna um grande desafio pois é mais difı́cil unificar e padronizar processos.
Mais pontos de falha - Por ser mais fácil promover novas funcionalidades, os
deploys se tornam cada vez mais frequentes. Isso significa que existe mais possibilida-
des para um sistema falhar, portanto é preciso estar atento e preparado quando esses
problemas acontecerem.
Recursos limitados - por cada time possuir o seu próprio contexto e a sua ma-
neira de trabalhar, é necessário buscar por profissionais mais especı́ficos para suprir as
demandas de um determinado time. Além disso, também é necessário um maior número
de máquinas, banco de dados, entre outros.

Arquitetura Baseada em Eventos

Uma arquitetura baseada em eventos, ou EDA, é um estilo de arquitetura de soft-


ware assı́ncrona utilizada para produzir sistemas de alto desempenho e altamente es-
caláveis [10].
13

A Figura 1 mostra um exemplo de um sistema que utiliza EDA para realizar a


comunicação entre os seus serviços.

Figura 1: Exemplo de sistema utilizando EDA

Fonte: Elaborado pelo Autor (2021).

Na imagem é possı́vel observar que, ao receber um evento de produto vendido, o


serviço responsável por manter a base dos produtos com o estado atual faz a atualização
no seu banco de dados para que este produto não fique mais disponı́vel para listagem.
Neste caso, refere-se a produtos que são exclusivos, ou seja, só possuem uma instância.
Uma arquitetura baseada em eventos é uma ótima abordagem quando se fala sobre
aplicações modernas e distribuı́das, pois possui um baixo acoplamento, ao ponto de os
produtores não saberem quais serão os consumidores de um dado evento ou quais são as
consequências da ocorrência deste evento [11].
EDAs são ideais para incrementar a agilidade do time e evoluir rápido um pro-
duto. São mais comumente utilizadas em aplicações que utilizam microsserviços ou que
possuem componentes desacoplados [12]. Existem dois tipos principais de EDAs: a que
utiliza um broker e a que utiliza um mediador. A grande diferença entre esses padrões é
que ao utilizar um broker estamos lidando com uma estrutura mais simples, onde não é
necessário uma orquestração central dos eventos. Enquanto que numa arquitetura utili-
zando um mediador, o evento inicial é orquestrado e pode sofrer alterações feitas pelo
mediador antes de ser enviado para os consumidores [10].
14

Ainda de acordo com [10], uma arquitetura baseada em eventos é ideal quando
estamos lidando com sistemas em que o usuário não precisa receber nenhum retorno
imediatamente, apenas saber que a ação foi aceita. Além disso, é muito interessante para
sistemas com processamentos complexos e dinâmicos.
Entretanto, é importante entender os trade-offs ao se utilizar uma arquitetura
baseada em eventos. Alguns dos principais benefı́cios em se utilizar uma EDA são: melhor
escalabilidade, melhor desempenho, melhor responsividade, entre outros. Enquanto que
entre os principais desafios podemos citar que uma EDA apenas suporta consistência
eventual de dados, pode ser mais difı́cil para testar e debugar, é mais difı́cil de se obter
controle sobre o fluxo de processamento, entre outros [10].

Filas de Mensagens

Uma fila é uma coleção de entidades esperando para serem processadas. Nessa
coleção, novos elementos são adicionados ao final da fila, enquanto que para retirar ele-
mentos é necessário se retirar da frente da fila. Ou seja, as filas obedecem a estrutura
First-In-First-Out. O primeiro a entrar numa fila é também o primeiro a sair. Sendo
assim, uma Fila é uma estrutura de dados linear [13].
Podemos afirmar, portanto, que uma fila de mensagens nada mais é que uma
maneira de garantir que as mensagens transportadas entre duas aplicações irão ser pro-
cessadas de maneira linear, através do uso de uma estrutura de dados bastante utilizada.
A arquitetura básica de uma fila de mensagens é simples: existem as aplicações
que são responsáveis por produzir as mensagens e jogá-las para uma fila (produtores)
e as aplicações que são responsáveis por retirar as mensagens da fila e trabalharem de
acordo com o dado contido na mensagem (consumidores). O responsável por fazer a
intermediação entre as duas aplicações e garantir que a fila está funcionando corretamente
é chamado de broker [14].
A Figura 2 mostra um exemplo de como funciona um sistema que utiliza uma fila
de mensagens na comunicação.
15

Figura 2: Fila de Mensagens

Fonte: Elaborado pelo Autor (2021).

Na imagem acima é possı́vel observar que a aplicação produtora envia uma men-
sagem para a fila, que por sua vez está sendo gerenciada por um broker. Este por sua
vez sabe quais são os consumidores interessados em receber este evento e então o evento
é enviado ao consumidor corretamente.

Dead Letter Queue

Dead Letter Queue é a fila utilizada para armazenar as mensagens das filas de ori-
gem que não foram consumidas e/ou processadas corretamente. As DLQs são muito úteis
para depurar aplicações ou o sistema de mensagem [5]. Cada gerenciador de mensagem
(broker ) tipicamente possui o seu próprio sistema para DLQs [15].
16

2.2 Medição de DevOps

Esta seção explica brevemente os conceitos de Monitoramento e Observabilidade.

Monitoramento

Monitoramento é um tema extremamente complexo. Ao pesquisar sobre o assunto,


não é difı́cil encontrar diferentes explicações e conceitos sobre o tema. Para o contexto
deste trabalho, vamos considerar o que é descrito em [16]. Monitoramento é uma maneira
de permitir que seja possı́vel entender qual o estado atual (ou passado) de um sistema
baseado em métricas e registros (logs) pré definidos. Conforme citado em [17], podemos
afirmar que existem dois tipos principais de monitoramento.
Monitoramento White-Box baseado nas métricas que são exportadas pelo sis-
tema e pela infraestrutura que o sitema está utilizando;
Monitoramento Black-Box monitoramento do comportamento visualizado pelo
usuário final.
No caso deste projeto, queremos entender quando as DLQs possuem mensagens,
porque isso significa que o processamento de alguma mensagem da fila principal falhou.
É importante que os desenvolvedores sejam alertados nesse caso para que possam agir o
mais rapidamente possı́vel, utilizando ferramentas que serão descritas no Capı́tulo 3.

Observabilidade

Observabilidade busca medir quão bem os responsáveis por um sistema conseguem


entender o estado do sistema a partir de outputs externos. É a observabilidade que permite
com que um sistema seja monitorável.
Para uma aplicação ser observável, é necessário que as pessoas desenvolvedoras por
esse sistema sejam capazes de entender o funcionamento interno da aplicação, além de
entender o estado do sistema em um dado momento e como ele chegou naquele estado [6].
Logs, métricas e traces (também conhecidos como os três pilares da observabili-
dade) são ferramentas que auxiliam a tornar os sistemas observáveis [18].
Os Logs são registros de eventos que permitem identificar comportamentos que
aconteceram no sistema. A partir dos logs, é possı́vel saber se o comportamento foi o
esperado ou se algo deu errado. É muito recomendado que esses registros sejam injetados
de uma maneira estruturada, seguindo um formato especı́fico, como por exemplo JSON,
17

para que esses logs sejam de fácil visualização e sejam buscáveis [18].
As Métricas são valores, normalmente quantidades ou medidas, agredados por
um perı́odo de tempo. É a partir das métricas que conseguimos saber como foi o uso de
CPU, memória ou até mesmo quantas requisições foram feitas para a nossa aplicação [18].
Os Traces são responsáveis por detalhar como cada requisição foi tratada na sua
aplicação. Qual foi o fluxo que essa requisição fez até chegar no ponto de falha ou até
finalizar com sucesso [18].

2.3 Sumário

Neste capı́tulo foram apresentados os conceitos de arquitetura de microsserviços,


arquiterura baseada em eventos, filas de mensagens, dead letter queue, monitoramento e
observabilidade. Estes conceitos são fundamentais para o entendimento e desenvolvimento
deste projeto.
O Capı́tulo 3 irá detalhar a arquitetura proposta para solucionar os problemas já
mencionados e quais as tecnologias que serão utilizadas para alcançar os objetivos deste
trabalho.
18

3 VISÃO GERAL DA ARQUITETURA PROPOSTA

Como mencionado no Capı́tulo 1, o objetivo deste trabalho é apresentar uma pro-


posta de arquitetura para monitoramento e reprocessamento de mensagens de DLQs.

Figura 3: Arquitetura proposta.

Fonte: Elaborado pelo Autor (2021).

A Figura 3 detalha como a nossa arquitetura irá funcionar. Vamos detalhar cada
um dos passos:

• Passo 1: o produtor irá enviar eventos para a fila principal;

• Passo 2: o consumidor irá consumir da fila principal e informar se ocorreu tudo


bem;

• Passo 3: caso tenha ocorrido alguma falha no consumo da mensagem, o evento será
enviado para uma DLQ;

• Passo 4: as pessoas responsáveis pelo sistema serão notificadas que existem men-
sagens na fila;

• Passo 5: uma pessoa responsável pelo sistema irá acionar a aplicação para repro-
cessar mensagens da DLQ;

• Passo 6: a aplicação para reprocessamento irá consumir os eventos que estão na


DLQ;

• Passo 7: a aplicação para reprocessar mensagens irá enviar os eventos para a fila
principal novamente;
19

Para implementar esta arquitetura, um conjunto de ferramentas e tecnologias am-


plamente adotadas pela indústria serão utilizadas. Precisaremos de pelo menos quatro
ferramentas/tecnologias para as seguintes partes:

• Um provedor do serviço de filas com suporte a DLQ (para os passos 1, 2, 3, 6 e


7). Alguma opções disponı́veis no mercado são Amazon SQS 1 , RabbitMQ 2 ,
3
ActiveMQ entre outros;

• Uma ferramenta para monitoração (para o passo 4), como por exemplo New Relic
4
, Rollbar 5 , Grafana 6
entre outros;

• Uma ferramenta para configurar infraestrutura em forma de código (para o passo


4). Terraform7 , Ansible8 e AWS Cloudformation9 são alguns exemplos;

• Uma ferramenta para automação de fluxo de trabalho (para os passos 5, 6 e 7).


Alguma ferramentas são: Github Actions10 , Jenkins11 , Gitlab12 entre outras;

3.1 Ferramentas Utilizadas

A seguir, serão apresentadas breves descrições sobre cada uma das ferramentas
utilizadas para o desenvolvimento deste projeto.

3.2 Amazon SQS

O Amazon SQS é um serviço de gerenciamento de Filas de Mensagens que permite


o desacoplamento e a escala de microsserviços, sistemas distribuı́dos e aplicações serverless
[19]. Usar o SQS vai permitir com que tenhamos um broker confiável e removerá toda
a complexidade relacionada à infraestrutura que terı́amos se fosse nossa responsabilidade
gerenciar e observar o serviço de mensagens.
1
https://aws.amazon.com/sqs/
2
https://www.rabbitmq.com/
3
https://activemq.apache.org/
4
https://newrelic.com/
5
https://rollbar.com/
6
https://grafana.com/
7
https://www.terraform.io/
8
https://www.ansible.com/
9
https://aws.amazon.com/cloudformation/
10
https://github.com/features/actions
11
https://www.jenkins.io/
12
https://about.gitlab.com/
20

O Amazon SQS oferece dois tipos de filas.

Standard Queues

• Taxa de transferência ilimitada: suporta um número ilimitado de transações por


segundo;

• At-Least-Once Delivery: cada mensagem é entregue pelo menos uma vez, mas oca-
sionalmente pode ser entregue mais de uma vez;

• Ordenamento de Melhor-Esforço: ocasionalmente as mensagens podem ser entregues


numa ordem diferente das que foram enviadas.

FIFO Queues

• Alta Taxa de Transferência: suporta um número alto de mensagens por segundo


(300 mensagens), porém não é ilimitado;

• Exactly-Once Delivery: cada mensagem é entregue uma única vez e permanece


disponı́vel até que seja consumida e processada corretamente;

• Entrega First-In-First-Out: A ordem de entrega das mensagens é exatamente a


mesma ordem em que elas chegam.

O Amazon SQS é um serviço amplamente utilizado em todo o mundo e vai nos


ajudar a focar no que realmente interessa no trabalho.

3.3 Datadog

O Datadog é uma plataforma de monitoramento e segurança para aplicações em


nuvem. Com o Datadog é possı́vel visualizar traces, métricas e registros de logs em um
único lugar, possibilitando que não só a aplicação, mas a infraestrutura e também os
serviços de terceiros, se tornem completamente observáveis [20].
O Datadog foi a ferramenta escolhida para observar e monitorar a nossa DLQ
no AWS, devido a ótima integração existente entre as duas plataformas. Com o Datadog
serão criados os alertas para quando houver mensagens na nossa DLQ e, assim, as pessoas
responsáveis pelo sistema poderem tomar ações imediatamente.
21

3.4 Terraform

O Terraform é uma ferramenta de software de código aberto que permite o geren-


ciamento (construção, manutenção e versionamento) de infraestrutura de forma segura
e eficiente através de código utilizando arquivos de configurações de forma declarativa
através da HashiCorp Configuration Language (HCL). Essa infraestrutura inclui desde
componentes de baixo nı́vel como instâncias de servidores e armazenamento até compo-
nentes de alto nı́vel, como entradas de DNS [21].
Com Terraform é possı́vel fazer o gerenciamento tanto de provedores públicos
quanto privados. Algumas boas práticas para uso do Terraform são descritas em [22].
Entre elas podemos citar:

• Sempre gerencie o estado do terraform salvando o arquivo tfstate em um armazena-


mento seguro com criptografia;

• Utilize variáveis como entrada;

• Utilize versionamento;

• Formate o Terraform utilizando terraform fmt;

• Use módulos compartilhados;

• Escreva testes automatizados;

• Mantenha pelo menos dois ambientes, um para produção e um para testes.

3.5 Github Actions

As Github Actions tem o intuito de auxiliar o desenvolvedor a automatizar o ciclo


de vida de desenvolvimento de Software. Essas actions são baseadas em eventos, permi-
tindo com que diversos comandos sejam executados após um evento especı́fico ocorrer.
Por exemplo, sempre que alguém subir um código novo para o repositório no Github,
um comando pode ser executado automaticamente para rodar os testes definidos no re-
positório [23]. Isso significa que com as Github Actions é possı́vel configurar o workflow
necessário para Integração e Deploy contı́nuo, mas, além disso, também é possı́vel execu-
tar qualquer outro tipo de automação, inclusive rodar trechos de código. Vamos abordar
alguns dos principais componentes do projeto Github Actions.
22

As Actions são comandos que são chamados dentro de steps para criar um job. É
o menor bloco de um workflow.
Um Step é uma tarefa individual responsável por executar comandos. Ele pode
ser um comando shell ou mesmo uma action. Todos os steps de um job rodam no mesmo
runner.
Um Evento é a atividade especı́fica que vai acionar um workflow. Por exemplo,
quando um pull request é aberto ou quando um commit é disparado.
Os Runners são servidores. A pessoa desenvolvedora pode utilizar runners que
são disponibilizados pelo Github ou pode utilizar o seu próprio runner. O runner é o
responsável por ouvir os jobs que precisam ser executados, rodá-los, dar reports sobre o
progresso, logs e retornar os resultados para o Github.
Um Job é um conjunto de steps que executam no mesmo runner. Por padrão, os
vários jobs dentro de um workflow rodam em paralelo, porém é possı́vel configurá-los para
rodar sequencialmente.
Os Workflows são procedimentos automáticos que a pessoa desenvolvedora adi-
ciona ao seu repositório. São compostos de um ou mais jobs e podem ser agendados ou
disparados por um evento.
Uma GitHub Action é dividida em três propriedades principais:

• name: é o nome da action.

• on: é uma lista com as situações em que a action será acionada.

• jobs: é uma lista com blocos de instruções do que deve ser feito na action. Cada
job tem um ou mais steps, que são passos que um job tem que executar. Os jobs são
executados, por padrão, de forma paralela. Entretanto, é possı́vel configurar para
que sejam executados de forma sequencial, através de dependências. Em cada job,
os steps que o formam são executados sequencialmente.

Neste trabalho será criado um Workflow no Github e será possı́vel entender melhor
a sua divisão e funcionamento.

3.6 Utilização dos Componentes

Durante o desenvolvimento do Capı́tulo 4, será possı́vel entender como cada uma


das tecnologias auxiliou para o cumprimento do objetivo deste trabalho, que é entregar
23

uma maneira de monitorar DLQs e de reprocessar mensagens de forma manual utilizando


GitHub Actions.

• O SQS será o responsável por hospedar a nossa fila principal e também a sua DLQ;

• O Datadog será o responsável por monitorar a nossa mensagem e disparar um


email quando algo tiver errado;

• Iremos utilizar o Terraform para criar os alertas necessários no Datadog;

• Haverá uma action do GitHub Actions no repositório GitHub da aplicação para


que possamos executar de forma manual o reprocessamento de mensagens da DLQ.

3.7 Sumário

Neste capı́tulo foi apresentada a arquitetura do nosso projeto inerente às tecno-
logias escolhidas, além de detalhar algumas opções disponı́veis no mercado para auxiliar
o desenvolvimento do projeto. Também foram feitas apresentações sobre as ferramentas
que serão utilizadas e em que parte do projeto cada uma será importante.
O Capı́tulo 4 irá detalhar a implementação da arquitetura proposta.
24

4 PROPOSTA EM AÇÃO

Este capı́tulo detalha a implementação de cada um dos componentes da arquitetura


proposta.

4.1 Criando a Base do Projeto

Antes de tudo é necessário criar a base para o projeto. Isso significa que serão
criadas a fila principal, o produtor, o consumidor e a DLQ configurada.

4.1.1 Criando a Fila no Amazon SQS

O primeiro passo é a criação uma fila no Amazon SQS utilizando o console do


Amazon Web Service (AWS). Para isso, é necessário pesquisar por SQS, conforme mostra
a Figura 4.

Figura 4: Pesquisa por SQS no console da AWS.

Fonte: Elaborado pelo Autor (2021).

Em seguida vamos criar uma fila no SQS com o tipo sendo FIFO e o nome sendo
tcc-esvm-ufpe.fifo, conforme exibido na Figura 5.
25

Figura 5: Criando fila no SQS.

Fonte: Elaborado pelo Autor (2021).

Na seção de configuração, será ativada a deduplicação de mensagens a partir do


conteúdo das mesmas. Isso será importante para que o SQS consiga garantir a entrega
das mensagens uma única vez (sem duplicações) sem que seja necessário enviarmos vários
atributos para isso, basta o conteúdo da mensagem ser diferente. A configuração fica da
seguinte maneira:

Figura 6: Criando fila no SQS.

Fonte: Elaborado pelo Autor (2021).


26

Após definir as configurações, é só clicar em salvar e a fila será criada. Ao abrir
os detalhes da fila criada anteriormente, será possı́vel ter uma visualização conforme a
Figura 7.

Figura 7: Exibição da fila SQS criada no modo FIFO.

Fonte: Elaborado pelo Autor (2021).

4.1.2 Configurando DLQ para a Fila

Uma vez que a fila principal foi criada no Amazon Simple Queue Service, é hora
de configurarmos a DLQ para quando as mensagens não forem processadas corretamente.
Para fazer isso, é necessário criar uma nova fila no SQS. Para isso, basta repetir os
passos definidos na seção 4.1.1, porém utilizando o nome tcc-esvm-ufpe-dlq.fifo, obtendo
o resultado exibido a seguir:

Figura 8: Exibição da fila SQS que será utilizada como DLQ.

Fonte: Elaborado pelo Autor (2021).

Após criar a fila que será utilizada como DLQ, é necessário acessar a página de
27

detalhes da nossa fila principal, ir na aba Dead-Letter Queue e clicar em editar. Em


seguida, descer até a seção Dead-letter queue e selecionar a fila que foi criada e configurar
o Maximum Receives para 1, conforme exibe a imagem a seguir:

Figura 9: Configurando uma DLQ para a fila principal.

Fonte: Elaborado pelo Autor (2021).

Ao final, ao acessar a fila principal, é possı́vel observar que agora ela possui uma
DLQ configurada:

Figura 10: Fila principal possui uma DLQ configurada.

Fonte: Elaborado pelo Autor (2021).


28

4.1.3 Criando Credenciais na AWS

Para poder executar as aplicações para produzir e consumir mensagens da nossa


fila principal, conforme descrito nas seções 4.1.4 e 4.1.5, será necessário gerar credenciais
de acesso para o nosso usuário.
Para isso, basta acessar a aba de Security Credentials conforme descrito na Figura
11.

Figura 11: Menu da conta da AWS.

Fonte: Elaborado pelo Autor (2021).

Em seguida, é preciso acessar a opção de Access keys (access key ID and secret
access key) e gerar uma nova Access Key, conforme exibido na Figura 12.

Figura 12: Gerando uma access key no AWS.

Fonte: Elaborado pelo Autor (2021).


29

4.1.4 Criando Produtor para a Fila

Agora que as filas foram configuradas de maneira simples no Amazon Simple Queue
Service, pode ser criada a aplicação que será responsável por enviar mensagens para a fila
principal.
Para criar esta aplicação, a linguagem escolhida foi Golang na versão 1.17. Entre-
tanto este projeto é agnóstico à linguagem de programação escolhida.
Para desenvolver a aplicação em Go, será utilizada a biblioteca github.com/aws/aws
-sdk -go/aws para fazer a comunicação com a AWS. O código final da aplicação é o
seguinte:
1 package main
2

3 import (
4 " fmt "
5 " time "
6

7 " github . com / aws / aws - sdk - go / aws "


8 " github . com / aws / aws - sdk - go / aws / credentials "
9 " github . com / aws / aws - sdk - go / aws / session "
10 " github . com / aws / aws - sdk - go / service / sqs "
11 )
12

13 func main () {
14 queueUrl := " https :// sqs . us - east -1. amazonaws . com /576308049910/ tcc -
esvm - ufpe . fifo "
15 accessKeyId := " A K I A Y M L V C 6 7 3 F O A L Q B U M "
16 accessSecret := " F 4V t P HG c 9 mB N V oJ k 1 56 / Thunk / q51IR /7 krU8H4u "
17 region := " us - east -1 "
18 messageGroupId := " test "
19

20 sess , err := session . N e w S e s s i o n W i t h O p t i o n s ( session . Options {


21 Config : aws . Config {
22 Region : & region ,
23 Credentials : credentials . N e w S t a t i c C r e d e n t i a l s ( accessKeyId ,
accessSecret , " " ) ,
24 },
25 })
30

26 if err != nil {
27 fmt . Println ( " failed to create aws session " , err )
28 return
29 }
30

31 svc := sqs . New ( sess )


32

33 _ , err = svc . SendMessage (& sqs . SendMessageInput {


34 MessageGroupId : & messageGroupId ,
35 MessageBody : aws . String ( " Sending a new message at : " + time . Now () .
String () ) ,
36 QueueUrl : & queueUrl ,
37 })
38 if err != nil {
39 fmt . Println ( " failed to send message " , err )
40 return
41 }
42

43 fmt . Println ( " message sent successfully " )


44 }

Ao executar a aplicação, deve ser obtida uma mensagem de sucesso:

Figura 13: Mensagem de sucesso do produtor.

Fonte: Elaborado pelo Autor (2021).

Com isso, ao acessar a fila principal na AWS, é possı́vel visualizar que existem
mensagens disponı́veis na fila através da aba Send and Receive Messages. Ao ser realizado
um poll da mensagem disponı́vel, é possı́vel visualizar o conteúdo da mensagem, conforme
exibido nas imagens a seguir:
31

Figura 14: Mensagens disponı́veis na fila principal.

Fonte: Elaborado pelo Autor (2021).

Figura 15: Conteúdo da mensagem disponı́vel na fila principal.

Fonte: Elaborado pelo Autor (2021).

4.1.5 Criando Consumidor para a Fila

Para criar esta aplicação, novamente a linguagem escolhida foi Golang na versão
1.17. Entretanto este projeto é agnóstico à linguagem de programação escolhida.
Para desenvolver a aplicação em Go, será utilizada a biblioteca github.com/aws/aws
-sdk -go/aws para fazer a comunicação com a AWS. O código final da aplicação é o
seguinte:
1 package main
2

3 import (
4 " fmt "
5 " time "
32

7 " github . com / aws / aws - sdk - go / aws "


8 " github . com / aws / aws - sdk - go / aws / credentials "
9 " github . com / aws / aws - sdk - go / aws / session "
10 " github . com / aws / aws - sdk - go / service / sqs "
11 )
12

13 func main () {
14 queueUrl := " https :// sqs . us - east -1. amazonaws . com /576308049910/ tcc -
esvm - ufpe . fifo "
15 accessKeyId := " A K I A Y M L V C 6 7 3 F O A L Q B U M "
16 accessSecret := " F 4V t P HG c 9 mB N V oJ k 1 56 / Thunk / q51IR /7 krU8H4u "
17 region := " us - east -1 "
18 messageGroupId := " test "
19

20 sess , err := session . N e w S e s s i o n W i t h O p t i o n s ( session . Options {


21 Config : aws . Config {
22 Region : & region ,
23 Credentials : credentials . N e w S t a t i c C r e d e n t i a l s ( accessKeyId ,
accessSecret , " " ) ,
24 },
25 })
26 if err != nil {
27 fmt . Println ( " failed to create aws session " , err )
28 return
29 }
30

31 svc := sqs . New ( sess )


32

33 _ , err = svc . SendMessage (& sqs . SendMessageInput {


34 MessageGroupId : & messageGroupId ,
35 MessageBody : aws . String ( " Sending a new message at : " + time . Now () .
String () ) ,
36 QueueUrl : & queueUrl ,
37 })
38 if err != nil {
39 fmt . Println ( " failed to send message " , err )
40 return
41 }
33

42

43 fmt . Println ( " message sent successfully " )


44 }

A grande diferença é que agora esta aplicação está recebendo uma mensagem a
partir da sessão da aws, ao invés de enviar como no código anterior.
Ao executar o código, é obtido o seguinte resultado:

Figura 16: Resultado do consumo da fila.

Fonte: Elaborado pelo Autor (2021).

Como é possı́vel reparar na imagem, a data e hora exibidas no conteúdo da men-


sagem são diferentes, pois foi realizado um novo teste.
Com isso, a base para o projeto está criada. Há uma fila com uma DLQ configurada
e duas aplicações, uma que fará a produção de mensagens e uma outra responsável pelo
consumo dessas mensagens. Para reduzir a complexidade, foram criadas duas aplicações
simples que trocam mensagens sem valor de negócio.

4.2 Criando o Projeto

Agora é possı́vel implementar a proposta arquitetural. Nesta seção será configurada


a integração entre Datadog e AWS, criar os alertas no Datadog utilizando Terraform e
também será criada a Github Action que permitirá o reprocessamento de mensagens da
DLQ.
34

4.2.1 Integrando Datadog a AWS

Para criar a integração do Datadog com a AWS, é necessário seguir alguns passos.
Primeiramente, será gerada uma nova API Key no Datadog para a integração. Para isso,
é só acessar a página de Application Keys, conforme exibido na Figura 17.

Figura 17: Acessando página de configurações pessoais no Datadog.

Fonte: Elaborado pelo Autor (2021).

Em seguida, é preciso criar uma nova chave com o nome tcc-esvm-ufpe e copiar o
ID desta chave:

Figura 18: Criando uma nova application key no Datadog.

Fonte: Elaborado pelo Autor (2021).

Agora é necessário acessar a página de integrações do Datadog e selecionar Amazon


Web Services, conforme exibido na imagem:
35

Figura 19: Procurando integração com AWS no Datadog.

Fonte: Elaborado pelo Autor (2021).

Neste momento é necessário garantir que o acesso ao SQS está habilitado. Para
isso, basta selecionar a aba de configurações:

Figura 20: Acesso ao SQS habilitado.

Fonte: Elaborado pelo Autor (2021).

Com isso pronto, é necessário configurar a conta da AWS para permitir que o Data-
dog consiga acessar e extrair as métricas. Isso é possı́vel ser feito de maneira automatizada
36

ou manual, conforme descrito na documentação do Datadog.


Por questões de simplicidade, este projeto irá utilizar a forma automatizada. Para
isso, basta selecionar a opção de configurar automaticamente utilizando o Cloudformation,
conforme indicado na figura:

Figura 21: Adicionar nova conta da AWS.

Fonte: Elaborado pelo Autor (2021).

Na nova aba que será aberta com um endereço do AWS, é preciso preencher o
campo de Datadog Key com a chave que havia sido gerada anteriormente:
37

Figura 22: Informar chave do Datadog na AWS.

Fonte: Elaborado pelo Autor (2021).

Em seguida, basta aceitar as configurações adicionais que o Cloudformation informa


e criar a stack:

Figura 23: Criando stack na AWS para o Datadog.

Fonte: Elaborado pelo Autor (2021).

Após configurar a conta com as permissões necessárias para o Datadog acessar a


AWS, é necessário preencher as informações do ID da conta e nome da conta no Datadog.
38

Assim o Datadog conseguirá acessar a AWS e ter acesso a todas as métricas para os
sistemas selecionados:

Figura 24: Preencher informações da conta AWS.

Fonte: Elaborado pelo Autor (2021).

Com isso, já é possı́vel visualizar algumas métricas sobre a fila principal. Para uma
breve visualização desses dados, basta acessar o Metrics Explrorer do Datadog e escolher
a seguinte métrica:

aws.sqs.number of messages received

Esta métrica da a visualização do número de mensagens que foram enviadas para


a fila principal:

Figura 25: Métrica de número de mensagens recebidas.

Fonte: Elaborado pelo Autor (2021).


39

4.2.2 Criando Alerta para a DLQ

Agora que o Datadog está integrado ao AWS, é possı́vel, enfim, configurar o moni-
toramento da DLQ. O primeiro passo será salvar algumas chaves do Datadog. Para isso,
basta acessar a aba de Organization Settings e salvar o valor da API Key:

Figura 26: Acessando API key do Datadog.

Fonte: Elaborado pelo Autor (2021).

Em seguida, acessar a Application Key que foi gerada na seção 4.2.1:

Figura 27: Acessando application key do Datadog.

Fonte: Elaborado pelo Autor (2021).

Com a Application Key e a API Key em mãos, é possı́vel configurar o módulo de


monitoramento do terraform. A seguinte estrutura para os arquivos será adotada:
40

Figura 28: Estrutura dos arquivos Terraform no repositório.

Fonte: Elaborado pelo Autor (2021).

O detalhamento de cada diretório e arquivo desta estrutura está presente a seguir:

• terraform/monitor é o módulo Terraform em que será definido o monitor (ou


alerta) a ser criado no Datadog. Esta pasta possui dois arquivos:

– main.tf é o arquivo que contém a inicialização do provider do Datadog e


também a definição de query para o alerta, mensagem de notificação, canal de
notificação, thresholds etc;

– variables.tf é o arquivo que define quais são as variáveis necessárias ao ins-


tanciar este módulo;

• terraform/main.tf é o arquivo que cria uma instância do módulo de monitora-


mento e informa os valores para cada uma das variáveis requeridas.

O conteúdo de cada um desses arquivos será explicitado a seguir.

terraform/monitor/main.tf

1 terraform {
2 re qu ir ed _p ro vi de rs {
3 datadog = {
4 source = " DataDog / datadog "
5 }
6 }
7 }
8

9 provider " datadog " {


10 api_key = " 41428292 b d f 6 a 0 b b f e b c 2 b 0 2 1 3 6 2 9 5 4 6 "
41

11 app_key = " c e d 0 d 4 c 2 2 b e 8 5 4 f b 8 2 8 4 b 1 0 3 1 b 1 e 1 5 6 1 f 3 7 f b 0 5 c "


12 }
13

14 resource " datadog_monitor " " a le rt _s qs _qt y_ ms gs " {


15 name = " Monitoring for # msgs on queue $ { var . queue } "
16 type = " metric alert "
17 message = " {{# is_alert }} # msgs on {{ queuename }} is higher than $ { var .
th re sh ol d_ cr it ic al }. Current value is {{ value }} {{/ is_alert }}\ n \ n
{{# is_recovery }} # msgs on queue {{ queuename }} is back to normal . {{/
is_recovery }}\ n $ { var . notify } "
18

19 query = " max ( last_5m ) : avg : aws . sqs .


a p p r o x i m a t e _ n u m b e r _ o f _ m e s s a g e s _ v i s i b l e { queuename : $ { var . queue }} >= $ {
var . th re sh ol d_ cri ti ca l } "
20

21 m oni to r_ th re sh ol ds {
22 critical = var . t hr es ho ld_ cr it ic al
23 cri tical_ recove ry = var . t h r e s h o l d _ c r i t i c a l _ r e c o v e r y
24 }
25

26 notify_no_data = false
27 ren otify_ interv al = 60
28 }

É preciso ficar atento a algumas definições deste arquivo, como por exemplo:
type indica qual tipo de monitor está sendo criado. No caso deste trabalho, foi
criado um alerta baseado em métricas.
message define a mensagem de alerta que será recebida quando o alerta estourar.
O que vem após o /is recovery indica para qual canal o alerta deve ser enviado. Isso foi
feito de forma customizável para que seja possı́vel reaproveitar em outras implementações.
query é o campo que define a query que este alerta observará. No caso deste
projeto, os alertas serão disparados quando houver mensagens em uma determinada fila,
mais especificamente uma DLQ.
monitor thresholds indica quais serão as condições para o alerta ser acionado e
qual a condição para se recuperar ao estado saudável.
renotify internal indica o intervalo, em minutos, em que o alerta irá enviar uma
nova notificação.
42

Como é possı́vel observar no código, são feitas referências a algumas variáveis:


var.queue, var.notify etc. Estas variáveis estão definidas no arquivo a seguir:

terraform/monitor/variables.tf

1 variable " queue " {


2 type = string
3 description = " Your queue name "
4 }
5

6 variable " notify " {


7 type = string
8 description = " Where to route alerts to . Will look something like
@pagerduty - < service > or @slack - < channel > etc . "
9 }
10

11 variable " t hr es ho ld_ cr it ic al " {


12 description = " Number of messages when to alert . "
13 default = 1
14 validation {
15 condition = coalesce ( var . threshold_critical , 0) >= 1
16 error_message = " The th re sh ol d_ cr it ic al must be between 1 and
infinty . "
17 }
18 }
19

20 variable " t h r e s h o l d _ c r i t i c a l _ r e c o v e r y " {


21 description = " Number of messages when to consider it back to normal . "
22 default = 0.9
23 validation {
24 condition = coalesce ( var . threshold_critical_recovery , 0) >= 0.1
25 error_message = " The t h r e s h o l d _ c r i t i c a l _ r e c o v e r y must be between 0.1
and < th re sh ol d_c ri ti ca l . "
26 }
27 }

Como citado anteriormente, esses dois arquivos definem o módulo de monitora-


mento. Agora é necessário instanciar este módulo criando um novo arquivo Terraform,
que é o arquivo que será utilizado para rodar o terraform plan e o terraform apply.
43

terraform/main.tf

1 module " d a t a d o g _ s q s _ q t y _ m s g s " {


2 source = " ./ monitor "
3

4 queue = " tcc - esvm - ufpe - dlq . fifo " // DLQ


5 notify = " @esvm@cin . ufpe . br " // Author Email
6

7 t hre sh ol d_ cr it ic al = 1
8 t h r e s h o l d _ c r i t i c a l _ r e c o v e r y = 0.9
9 }

Neste arquivo, é preciso informar o nome da DLQ criada anteriormente tcc-esvm-


ufpe-dlq.fifo e o canal utilizado para a notificação dos alertas @esvm@cin.ufpe.br - o @ na
frente indica que será enviado para um email.
Para criar o alerta, é necessário acessar o diretório terraform/ e executar os se-
guintes comandos:

1 terraform init
2 terraform plan
3 terraform apply - auto - approve

Ao executar o terraform plan dentro do diretório, o seguinte resultado é obtido:


1 Terraform used the selected providers to generate the following
execution plan . Resource actions are indicated with the following
symbols :
2 + create
3

4 Terraform will perform the following actions :


5

6 # module . d a t a d o g _ s q s _ q t y _ m s g s . datadog_monitor . a le rt _sq s_ qt y_ ms gs will


be created
7 + resource " datadog_monitor " " a ler t_ sq s_ qt y_ ms gs " {
8 + evaluation_delay = ( known after apply )
9 + id = ( known after apply )
10 + include_tags = true
11 + message = <<- EOT
44

12 {{ # is_alert }} # msgs on {{ queuename }} is higher than 1.


Current value is {{ value }} {{/ is_alert }}
13

14 {{ # is_recovery }} # msgs on queue {{ queuename }} is back to


normal . {{/ is_recovery }}
15 @esvm@cin . ufpe . br
16 EOT
17 + name = " Monitoring for # msgs on queue tcc - esvm -
ufpe - dlq . fifo "
18 + new_host_delay = 300
19 + notify_no_data = false
20 + query = " max ( last_5m ) : avg : aws . sqs .
a p p r o x i m a t e _ n u m b e r _ o f _ m e s s a g e s _ v i s i b l e { queuename : tcc - esvm - ufpe - dlq .
fifo } >= 1 "
21 + renot ify_in terval = 60
22 + r e q ui r e _f u l l_ w i nd o w = true
23 + type = " metric alert "
24

25 + mo ni to r_ th re sh ol ds {
26 + critical = "1"
27 + criti cal_re covery = " 0.9 "
28 }
29 }
30

31 Plan : 1 to add , 0 to change , 0 to destroy .

Após executar o comando terraform apply -auto-approve, é possı́vel visualizar o


alerta criado no Terraform:

Figura 29: Alerta criado no Terraform.

Fonte: Elaborado pelo Autor (2021).

Com isso, poucos minutos após a criação do alerta, um email foi disparado pelo
45

Datadog alertando sobre a DLQ possuir mensagens e foi possı́vel visualizar na interface
do Datadog o monitor com status de erro, conforme exibido na Figura 30 e na Figura 31:

Figura 30: Email recebido do Datadog alertando sobre erro.

Fonte: Elaborado pelo Autor (2021).

Figura 31: Alerta no Datadog com status de erro.

Fonte: Elaborado pelo Autor (2021).

Isso aconteceu porque a aplicação responsável por consumir os eventos processou


a mensagem, mas não informou ao SQS que deu tudo certo no consumo, com isso, auto-
46

maticamente a mensagem não é deletada e vai parar na DLQ. Para resolver isso, basta
fazer um pequeno ajuste no código do consumidor:
1 output , err := svc . ReceiveMessage (& sqs . R e ce i v eM e s sa g e In p u t {
2 QueueUrl : & queueUrl ,
3 M a xN u m be r O fM e s sa g e s : & maxNumberOfMessages ,
4 })
5 if err != nil {
6 fmt . Println ( " failed to download messages " , err )
7 return
8 }
9

10 // new code begin


11 if len ( output . Messages ) > 0 {
12 for _ , message := range output . Messages {
13 svc . DeleteMessage (& sqs . De le te Me ss age In pu t {
14 QueueUrl : & queueUrl ,
15 ReceiptHandle : message . ReceiptHandle ,
16 })
17

18 fmt . Println ( message . String () )


19 }
20 }
21 // new code end

Isso fará com que as mensagens sejam consumidas e removidas da fila corretamente.

4.2.3 Criando Github Action para Reprocessar Mensagens

Para reprocessar as mensagens da DLQ e fazer com que elas sejam processadas
corretamente na fila principal, dado que o código da aplicação consumidora foi ajustado
na seção anterior, este trabalho se propõe a criar uma Github Action com a seguinte
definição:

1 name : Replay messages from SNS DLQ


2 description : Move messages from Dead Letter Queue to the main queue
3 inputs :
4 source_queue :
5 description : " The queue you want to move messages from . "
6 required : true
47

7 des tinati on_que ue :


8 description : " The queue you want to move messages to . "
9 required : true
10 aws _acces s_key_ id :
11 description : " The AWS access key id from the user with access to the
queues "
12 required : true
13 aws_secret_access_key :
14 description : " The AWS secret access key from the user with access to
the queues "
15 required : true
16 aws_region :
17 description : " The region of the user account "
18 default : us - east -1
19

20 runs :
21 using : " composite "
22 steps :
23 - name : Run Message Mover
24 shell : bash
25 env :
26 AWS_ ACCES S_KEY_ ID : $ {{ inputs . aw s_acce ss_key _id }}
27 A W S _ S E C R E T _ A C C E S S _ K E Y : $ {{ inputs . a w s _ s e c r e t _ a c c e s s _ k e y }}
28 AWS_REGION : $ {{ inputs . aws_region }}
29 SOURCE_QUEUE : $ {{ inputs . source_queue }}
30 DEST INATI ON_QUE UE : $ {{ inputs . de stinat ion_qu eue }}
31 run : |
32 git clone https :// github . com / esvm / sqsmover . git && echo " cloned "
33 sleep 2
34 cd ./ sqsmover /
35 GO111MODULE = on go run - mod vendor ./ main . go -- source $ {
SOURCE_QUEUE } -- destination $ { DESTIN ATION_ QUEUE }

É necessário estar atento a algumas configurações desta action:

• inputs: este campo define quais serão os atributos necessários informar de entrada
ao utilizar a action para que seja possı́vel executar o comando para reprocessar
mensagens corretamente;

• steps: define quais serão os steps que a action irá executar;


48

• run: aqui se define qual é o comando especı́fico que o step irá executar.

Esta action possui apenas um step, que é o passo que irá executar o comando de
mover mensagens de uma fila para outra. Este comando executa uma aplicação em go
hospedada no Github de maneira pública.

Figura 32: Trecho de código da aplicação13 responsável por mover mensagens de uma fila
para outra.

Fonte: Elaborado pelo Autor (2021).

Agora que a action foi criada, é necessário definir um Workflow que irá executar
essa action:
1 name : Replay messages from SNS DLQ
2 on :
3 wor kflow_ dispat ch :
4 inputs :
5 dlqQueue :
6 description : " Pass the queue you want to move messages from "
7 required : true
8 destinationQueue :
9 description : " Pass the queue you want to move messages to "
10 required : true
11

13
https://github.com/esvm/sqsmover/blob/main/main.go
49

12 jobs :
13 replay - messages :
14 runs - on : ubuntu - latest
15 steps :
16 - name : Checkout GitHub Action Repo
17 uses : actions / checkout@v2
18 with :
19 repository : esvm / tcc
20 ref : main
21 token : $ {{ secrets . GITHUB_TOKEN }}
22 path : . github / actions / esvm / tcc
23

24 - name : Replay messages in DLQ


25 uses : ./. github / actions / esvm / tcc / actions
26 with :
27 source_queue : $ {{ github . event . inputs . dlqQueue }}
28 des tinati on_que ue : $ {{ github . event . inputs . destinationQueue }}
29 aws _acces s_key_ id : A K I A Y M L V C 6 7 3 F O A L Q B U M
30 a w s _ s e c r e t _ a c c e s s _ k e y : F4 V t PH G c 9m B N Vo J k 15 6 / Thunk / q51IR /7
krU8H4u

Decorrendo sobre este arquivo:

• on: aqui se define qual será o evento que irá acionar este workflow. Neste projeto,
espera-se que o reprocessamento de mensagens seja feito de forma manual, por conta
disso o valor workflow dispatch é preenchido;

• inputs: este campo define quais são as entradas necessárias para executar este
workflow. Isso irá criar uma interface no Github para informar os valores de entrada,
conforme exibido na Figura 33;

• jobs: define quais serão os processos que irão rodar neste workflow;

• steps: define quais serão as ações executadas em cada um dos jobs. No caso deste
trabalho, será utilizada a action customizada que foi criada anteriormente. Para
isso, é necessário fazer o download dessa action dentro do runner, utilizando a
action pública do GitHub actions/checkout@v2. Agora que o arquivo da action
foi baixado, é necessário referenciá-lo. Para isso, basta informar o caminho deste
50

arquivo no repositório. Em seguida, são preenchidos todos os inputs que são exigidos
pela action utilizando a tag with.

Figura 33: Interface para acionar o workflow no Github.

Fonte: Elaborado pelo Autor (2021).

Com o workflow criado e no repositório do projeto, agora é possı́vel acessar o


Github e executar este workflow para reprocessar as mensagens da DLQ. Para isso, basta
selecionar a aba de Actions no Github, clicar no workflow disponı́vel, clicar em Run
workflow, preencher os inputs corretamente e em seguida acionar o workflow. Em sı́ntese,
é necessário fazer o que está na imagem a seguir:
51

Figura 34: Acionando workflow no Github

Fonte: Elaborado pelo Autor (2021).

Após acionarmos o workflow, o seguinte resultado é obtido:

Figura 35: Resultado do workflow de reprocessar mensagens.

Fonte: Elaborado pelo Autor (2021).

Como é possı́vel visualizar na imagem, as seis mensagens que estavam na DLQ


foram movidas novamente para a fila principal. Agora, se a aplicação consumidora for
executada novamente com a alteração que foi implementada, o seguinte resultado será
obtido:
52

Figura 36: Rodando consumidor novamente após as mensagens serem movidas da DLQ
para a fila principal.

Fonte: Elaborado pelo Autor (2021).

Em seguida, o Datadog disparou um alerta avisando que o monitor se recuperou e


a DLQ está sem nenhuma mensagem novamente, ou seja, a aplicação está no seu estado
saudável novamente:
53

Figura 37: Aviso do Datadog de recuperação do estado da DLQ

Fonte: Elaborado pelo Autor (2021).


54

5 CONCLUSÃO E TRABALHOS FUTUROS

Arquitetura Baseada em Eventos é realmente uma arquitetura de software muito


poderosa e que deve ser sempre levada em consideração, principalmente pelos times que
trabalham com muitos microsserviços e podem realizar processamento assı́ncrono.
Um grande aliado à implementação de uma arquitetura baseada em eventos é o
Amazon Simple Queue Service. Um produto amplamente utilizado no mercado que auxilia
a implementação de filas e retira toda a complexidade de infraestrutura de um Message
Broker. Além disso, o suporte à Dead-Letter Queue facilita bastante o trabalho da pessoa
desenvolvedora no dia a dia, principalmente para entender porque o processamento de
uma determinada mensagem falhou.
Entretando, é muito comum que as mensagens da DLQ sejam esquecidas e nenhuma
ação efetiva seja tomada. Para solucionar isso, é importante criar um monitoramento
efetivo para essas filas. O Datadog é uma plataforma extremamente poderosa e nos
permite realizar esse monitoramento sem muitas dificuldades, além de que é possı́vel
utilizar o Terraform para gerenciar a sua infraestrutura.
As Github Actions surgem como grandes aliadas ao dia a dia das pessoas desenvol-
vedoras, permitindo automatizar processos de maneira simples e através de uma interface
que as pessoas desenvolvedores estão habituadas a utilizarem no dia a dia.
Este trabalho conseguiu alcançar o resultado esperado: permitir o reprocessamento
manual das mensagens das Dead-Letter Queues a ponto de não causar danos e frustrações
nos clientes, para os casos em que as mensagens possuem um valor de negócio, a partir
do monitoramento dessas filas e a notificação em tempo real das pessoas desenvolvedores
responsáveis por manter o projeto. No caso deste trabalho, por focar em mensagens que
possuem um valor de negócio, usualmente é necessário investigar e entender o motivo da
falha que levou a mensagem ser movida para a DLQ antes de reprocessá-las novamente.
Todo o código criado e utilizado neste projeto está disponı́vel de maneira pública
em https://github.com/esvm/tcc/.
55

REFERÊNCIAS

[1] FOWLER, S. J. Production-Ready Microservices. O’Reilly Media, Inc., v. 1, p.


Chapter 4, December 2016. Available at: <https://abre.ai/dAas>.

[2] RICHARDS, N. F. M. Fundamentals of Software Architecture. O’Reilly Media, Inc.,


v. 1, p. Chapter 4, January 2020. Available at: <https://abre.ai/dAar>.

[3] RICHARDS, M. Software Architecture Patterns. O’Reilly Media, Inc., v. 1, p.


11–18, Feb 2015. Available at: <https://www.oreilly.com/library/view/software-
architecture-patterns/9781491971437/ch02.html>.

[4] Amazon Web Services. What is a Message Queue? Available at:


<https://aws.amazon.com/message-queue/>. Accessed in: 30-Sep-2021.

[5] SAHAY, S. M. S. A Study on Developing Resilient Big Data Stream Proces-


sing Applications using Apache Kafka. International Journal of Scientific Rese-
arch and Engineering Development, p. 1434 – 1438, May-June 2021. Available at:
<https://abre.ai/dAaq>.

[6] SRIDHARAN, C. Distributed Systems Observability. O’Reilly Media, Inc., v. 1, p.


Chapter 2, July 2018. Available at: <https://abre.ai/dAat>.

[7] NEWMAN, S. Building Microservices. O’Reilly Media, Inc., v. 1, p. Chapter 1, Fe-


bruary 2015. Available at: <https://abre.ai/dAbw>.

[8] NEWMAN, S. Building Microservices. O’Reilly Media, Inc., v. 1, p. Chapter 3, Fe-


bruary 2015. Available at: <https://abre.ai/dAbM>.

[9] FOWLER, S. J. Production-Ready Microservices. O’Reilly Media, Inc., v. 1, p.


Chapter 1, December 2016. Available at: <https://abre.ai/dAbD>.

[10] RICHARDS, N. F. M. Fundamentals of Software Architecture. O’Reilly Media,


Inc., v. 1, p. Chapter 14, January 2020. Available at: <https://abre.ai/dAcb>.

[11] RedHat. O que é arquitetura orientada a eventos? Available at:


<https://www.redhat.com/pt-br/topics/integration/what-is-event-driven-
architecture>. Accessed in: 30-Sep-2021.
56

[12] Amazon Web Services. What is an Event-Driven Architecture? Available at:


<https://aws.amazon.com/event-driven-architecture/>. Accessed in: 24-Nov-2021.

[13] BAKA, B. Python Data Structures and Algorithms. O’Reilly Media, Inc., v. 1, p.
Queues Section, May 2017. Available at: <https://abre.ai/dAcq>.

[14] Microsoft. Service-to-service communication. Available at:


<https://abre.ai/dAcy>. Accessed in: 30-Nov-2021.

[15] IBM. Dead-letter queues. Available at: <https://www.ibm.com/docs/en/ibm-


mq/9.0?topic=components-dead-letter-queues>. Accessed in: 24-Nov-2021.

[16] Google Cloud. DevOps measurement: Monitoring and observability. Available at:
<https://cloud.google.com/architecture/devops/devops-measurement-monitoring-
and-observability>. Accessed in: 24-Nov-2021.

[17] Ewaschuk, R. Monitoring Distributed Systems. Available at:


<https://sre.google/sre-book/monitoring-distributed-systems/>. Accessed in:
24-Nov-2021.

[18] SRIDHARAN, C. Distributed Systems Observability. O’Reilly Media, Inc., v. 1, p.


Chapter 4, July 2018. Available at: <https://abre.ai/dAcF>.

[19] Amazon Web Services. Amazon Simple Queue Service. Available at:
<https://aws.amazon.com/sqs/>. Accessed in: 24-Nov-2021.

[20] Datadog. About. Available at: <https://www.datadoghq.com/about/leadership/>.


Accessed in: 24-Nov-2021.

[21] Hashicorp. Introduction to Terraform. Available at:


<https://www.terraform.io/intro/index.html>. Accessed in: 24-Nov-2021.

[22] BRIKMAN, Y. Terraform: Up and Running. O’Reilly Media, Inc., v. 1, p. Chapter


6, March 2017. Available at: <https://abre.ai/dAc6>.

[23] Github Docs. Understanding GitHub Actions. Available at:


<https://docs.github.com/en/actions/learn-github-actions/understanding-github-
actions>. Accessed in: 24-Nov-2021.

Você também pode gostar