Enviando e recebendo mensagens no AWS SQS com Spring Boot

Nesse artigo vamos abordar passo a passo como fazer o envio e recebimento de mensagens do serviço AWS SQS (Amazon Queue Service) utilizando aplicações Spring Boot.

Com aplicações cada vez mais modernas e escaláveis, nascendo já na cloud, o uso de uma fila pode acabar sendo imprescindível quando você está trabalhando com aplicações distribuídas, o processamento de informações de forma assíncrona tem ganhos tanto em performance quanto em custos.

Quando precisamos realizar essas implementações geralmente surge muitas dúvidas principalmente no uso da ferramenta, é muito comum a utilização do Apache Kafka para implementações desse tipo, mas é nessa hora que devemos fazer a pergunta é necessário realmente utilizar o Kafka? Teremos tanto processamento para ter uma ferramenta com tamanha escalabilidade? E o custo como ficaria?

Muitas dessas perguntas podem incomodar da implementação e devemos considerar que as principais clouds disponíveis hoje no mercado possuem outras implementações de fila, que são escaláveis e auto gerenciadas, trazendo grandes ganhos em performance, custo e produtividade.

No caso da AWS (Amazon Web Services) o serviço de fila é o AWS SQS, grandes aplicações utilizam-se desse serviço, que garante performance e escalabilidade, a seguir vamos ensinar como conectar sua aplicação desenvolvida com o framework Spring a esse serviço utilizando-se do Spring Cloud.

Configurando nosso projeto

Para configurar nosso projeto vamos precisar adicionar algumas dependências da lib Spring Cloud, para isso vamos precisar editar nosso arquivo pom.xml, como no exemplo a seguir:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.2.4</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.artefatox</groupId>
	<artifactId>connsqs</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>connsqs</name>
	<description>Exemplo de conexão com AWS SQS</description>
	
  <properties>
		<java.version>17</java.version>
	</properties>


	<dependencies>
		...outras dependencias

		<dependency>
			<groupId>io.awspring.cloud</groupId>
			<artifactId>spring-cloud-aws-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>io.awspring.cloud</groupId>
			<artifactId>spring-cloud-aws-starter-sqs</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>software.amazon.awssdk</groupId>
				<arfifactId>bom</arfifactId>
				<version>2.20.43</version>
			</dependency>
			<dependency>
				<groupId>io.awspring.cloud</groupId>
				<artifactId>spring-cloud-aws-dependencies</artifactId>
				<version>3.0.0</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>
pom.xml

É necessário adicionar o dependency management para ajudar a gerenciar as versões corretas das dependências que vamos utilizar e também as dependências do Spring Cloud que encapsulam as dependências do SDK disponibilizado pela AWS.

A grande vantagem de utilizar o Spring Cloud é porque ele vai incorporar o funcionamento de conexão com a fila ao próprio ecossistema do Spring, facilitando muito a implementação e mantendo o padrão do codificação da nossa aplicação.

Agora você precisará ter acesso a uma conta AWS e criar uma fila no SQS, também precisará de credenciais do tipo Access Key e Secret Key, que podem ser criadas no painel do IAM em seu console, a criação dessas chaves de acesso só é necessária pois vamos executar a nossa aplicação local, em caso de ela ser executada na própria AWS o ideal é você criar uma role com permissão a acessar o serviço e atribuir ao contêiner ou ec2 que estiver executando a aplicação.

Implementando o Listener do AWS SQS

Com a fila já criada vamos implementar a classe que será responsável por fazer a leitura das mensagens, essa implementação de fato é bem simples e objetiva.

package com.artefatox.connsqs;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;

import io.awspring.cloud.sqs.annotation.SqsListener;

@Service
public class AwsSqsListener {

	private static final Logger LOGGER = LoggerFactory.getLogger(AwsSqsListener.class);
	
	@SqsListener(value = "sample")
	public void onMessage(Message<?> message) {
		LOGGER.info("Mensagem recebida: {}", message.getPayload());
	}
}
AwsSqsListener.java

Na nossa classe anotamos ela com @Service para ficar no contexto do Spring facilitando a injeção de dependência, e também o método onMessage com a anotação @SqsListener, recebendo o nome da fila como valor, essa anotação vai fazer o trabalho de direcionar as mensagens recebidas daquela fila para esse método, dentro do método apenas estamos imprimindo a mensagem, mas é ai que deveria ficar sua implementação responsável por tratar a mensagem.

Implementando o Publisher do AWS SQS

Agora vamos dar atenção ao publicador de mensagens, geralmente a abordagem é ter o publicador em um serviço e o responsável por escutar as mensagens em outro, vamos fazer ambos em apenas um serviço para ficar mais simples e didático.

package com.artefatox.connsqs;

import org.springframework.stereotype.Service;

import io.awspring.cloud.sqs.operations.SqsTemplate;

@Service
public class AwsSqsPublisher {

	private final SqsTemplate template;

	public AwsSqsPublisher(SqsTemplate template) {
		this.template = template;
	}
	
	public void send(String queueName, String message) {
		template.send(queueName, message);
	}
}
AwsSqsPublisher.java

Note que a implementação também é bem simples precisando apenas utilizar a classe SqsTemplate que é nos fornecido pela própria biblioteca, como nossa classe é anotada com @Service o próprio framework se encarregará de fazer a injeção de dependência da implementação para nós.

Configurando as credenciais e região

Para que nosso serviço saiba quais credencias utilizar e em qual região se encontra a fila que criamos é necessário adicionar essas informações no nosso arquivo application.properties, como no exemplo a seguir:

spring.cloud.aws.sqs.region=us-east-1
spring.cloud.aws.credentials.accessKey=AXPBOD...
spring.cloud.aws.credentials.secretKey=badkkhHohodh...
application.properties

Testando o funcionamento

Para testar o funcionamento da conexão, assim como envio e recebimento de mensagens, vamos criar um endpoint simples que faz o envio da mensagem, e como temos o log no recebimento vamos saber se o serviço recebe a mesma informação enviada.

package com.artefatox.connsqs;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/example")
public class ExampleController {

	private final AwsSqsPublisher publisher;
	
	public ExampleController(AwsSqsPublisher publisher) {
		this.publisher = publisher;
	}
	
	@PostMapping
	public void endpoint(@RequestBody String message) {
		publisher.send("sample", message);
	}

}
AwsSqsPublisher.java

Agora podemos executar a aplicação e chamar o endpoint example com o método Post e validar o funcionamento.

Conclusão

Nesse artigo mostramos como é fácil conectar sua aplicação Spring Boot com o serviço de fila AWS SQS utilizando as bibliotecas do Spring Cloud.
Esse tipo de implementação é bem interessante para fazer serviços cada vez mais escaláveis, e fazer comunicação indireta entre serviços, trazendo para seu projeto processamento distribuído e de forma assíncrono.

Links úteis

Mauricio Lima
Mauricio Lima

Bacharel em Ciência da Computação, profissional dedicado ao desenvolvimento de software e entusiasta da tecnologia.

Artigos: 65