LocalStack: enviando e consumindo mensagens com SQS, SNS, S3, Spring Boot e a API Oficial da Marvel

Antes de Começar

Recomendo a leitura dos artigos abaixo antes de iniciar:

Introdução

O nosso BFF que pesquisa informações sobre personagens e detalhes das histórias da Marvel, também retorna as URL’s das imagens dos personagens.

Vamos obter essas imagens e gravar em um bucket S3 e disponibilizar um endpoint na nossa API para retornar as imagens.

Como esse processo requer acesso a uma URL externa, a geração de um arquivo e gravação em um bucket S3, vamos executar de forma assíncrona toda vez que pesquisamos um personagem.

Para isso vamos utilizar os serviços SNS e SQS da AWS.

O SNS é um sistema de notificação que envia mensagem para um e-mail, SMS ou para uma fila de mensagens como o SQS.

O SQS é um sistema de mensagem da AWS semelhante a outros sistemas de fila como Apache Kafka, Apache ActiveMQ e etc.

Quando a mensagem chegar ao SQS, um Worker Spring processará a mensagem e irá gravar o arquivo em um bucket S3.

Desenho da Solução

Abaixo segue o desenho da nossa solução usando SNS e SQS:

Criando SNS e SQS no LocalStack

Execute os comandos para criar a fila no SQS e o tópico no SNS.

Além disso é necessário efetuar a inscrição da fila SQS no tópico do SNS. Essa inscrição fala para o SNS, qual serviço a notificação deverá ser encaminhada.

aws --endpoint http://localhost:4566 --profile localstack sqs create-queue --queue-name marvelThumbnailImageQueueaws --endpoint http://localhost:4566 --profile localstack sns create-topic --name marvelThumbnailImageNotificationaws --endpoint http://localhost:4566 --profile localstack sns subscribe --topic-arn arn:aws:sns:us-east-1:000000000000:marvelThumbnailImageNotification --protocol sqs --notification-endpoint http://localhost:4566/queue/marvelThumbnailImageQueue

Dependências da Aplicação

Incluir as dependências em seu pom.xml para usar o SQS e o SNS:

Configurações para o LocalStack

No arquivo bootstrap.yml, configurar as URL’s do SQS, SNS e do S3 apontando para o LocalStack:

Para o S3, sempre usar a URL acima pois o o SDK da AWS concatena o nome do bucket com a URL da AWS. O LocalStack cria esse endereço para funcionar o acesso local ao bucket S3, simulando a URL pública da AWS.

Enviando notificação para o SNS

Usando o Spring Cloud podemos facilmente enviar mensagens para um tópico do SNS, usando a classe NotificationMessagingTemplate.

No nosso exemplo, estamos enviando uma notificação com header.

O SNS tem um formato padrão de envio de mensagens para o SQS.

O campo Message, representa a mensagem enviada pela aplicação para o SNS e consumida pelo SQS. O valor desse campo contém a URL da imagem do personagem da Marvel.

O campo MessageAttributes contém os headers da mensagem. No nosso exemplo o header possui os detalhes do personagem selecionado através do header marvelCharacter.

Consumindo mensagens do SQS

Usando a anotação @SqsListener, temos um listener que irá consumir as mensagens que chegam no SQS:

Salvando uma imagem no S3

Iremos obter a imagem através da URL especificada na mensagem enviada pelos SNS e salvar em um bucket do S3 de acordo com o tipo especificado.

Caso o arquivo exista, o mesmo não será criado no S3, informando uma mensagem de erro:

Como foi mencionado no artigo anterior: para gravar arquivos no bucket S3, iremos usar a interface ResourceLoader. Essa interface tem como objetivo, obter informações de arquivos do sistema operacional, classpath ou de outras origens.

No nosso caso essa interface irá gravar um arquivo no bucket S3. Quando especificamos o caminho s3://bucket/arquivo o objeto é gravado diretamente no S3:

Pesquisando arquivos no S3

Para efetuar a pesquisa de um arquivo dentro de um bucket S3, podemos usar a interface ResourcePatternResolver que tem um funcionamento semelhante ao ResourceLoader.

Nesse caso, passamos um filtro de pesquisa usando o padrão ant-style wildcard pattern.

Por exemplo:

s3://%s/%s*.*

No nosso código, vamos pesquisar todos os arquivos que comecem com um determinado termo.

Por exemplo:

s3://marvelcharacter/hulk*.*

Essa operação pode ocasionar lentidão, de acordo com a quantidade de arquivos dentro de um bucket.

Obtendo as imagens

Dentro da API, teremos um endpoint que efetuará a busca da imagem de um personagem. O Content-Type dessa operação, deverá ser image/jpeg tanto no produces, quanto no consumes da anotação do @GetMapping:

A camada de serviço, efetua a pesquisa dos arquivos e no header de resposta, retorna a quantidade de arquivos encontrados e sempre posiciona para o primeiro arquivo da lista.

Abaixo segue o retorno da imagem dentro do Postman:

Podemos ver o retorno dos headers, o total de arquivos encontrados e nome do arquivo selecionado no momento:

Usando o header denominado offset do request, podemos visualizar a outras imagens encontradas de acordo com o limite total da busca:

Conclusão

Usando o SNS e o SQS, podemos ter um sistema de fila muito robusto para processamento de operações assíncronas. O Spring Cloud e Spring Boot facilitam bastante o uso dessas tecnologias, principalmente quando trabalhamos com operações de busca e criação de arquivos em um bucket S3.

Repositório do Git

Até a próxima!

--

--

📺+ de 20 anos gerando código fonte em Java, Arquiteto Java, Desenvolvedor Java, Professor Universitário e Colecionador de Videogames

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store