Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
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.
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.
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.javaNa 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.
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.javaNote 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.
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.propertiesPara 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.javaAgora podemos executar a aplicação e chamar o endpoint example com o método Post e validar o funcionamento.
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.