Fala galera, beleza?

No post de hoje vou mostrar como simular alguns recursos da aws em sua máquina local utilizando o localstack. O lema do projeto é “Desenvolva e teste seus aplicativos na nuvem offline” e já me salvou muito quando fiquei sem acesso a internet.

Além de fornecer um ambiente offline, o LocalStack é muito bom para ambientes nos quais o desenvolvedor não tem acesso as configurações da aws, por exemplo, por questões de política de segurança da empresa.

Como exemplo de utilização dessa tecnologia, veremos na prática a leitura de uma fila sqs utilizando um projetinho Java com o aws sdk. Bora lá? =)

Subindo o LocalStack

A primeira ação que tomaremos será subir o LocalStack na nossa máquina. Vou utilizar a imagem docker oficial disponibilizada por eles. Para facilitar nossas vidas, há um arquivo docker-compose disponível no github do projeto.

Como usaremos somente o serviço de fila, delimitei no docker-compose abaixo que somente o SQS será habilitado e responderá na porta 4576.

version: '2.1'

services:
  localstack:
    image: localstack/localstack
    ports:
      - "4576:4576"
      - "8080:8080"
    environment:
      - SERVICES=sqs

Para subir o container, utilize o comando abaixo:

$ docker-compose up

Uma vez que o LocalStack estiver rodando na sua máquina, você poderá acessar a interface web através da url http://localhost:8080.

Criando uma fila com o aws-cli

Para testar se o SQS está funcionando, será necessário instalar o aws-cli, que é a interface de linha de comando da aws.

Os possíveis comandos para manipular uma fila podem ser vistos neste link.

Exemplo de como criar uma fila utilizando o endpoint local:

$ aws --endpoint-url=http://localhost:4576 sqs create-queue --queue-name teste
{
    "QueueUrl": "http://localhost:4576/queue/teste"
}

Exemplo de envio de uma mensagem para a fila:

$ aws --endpoint-url=http://localhost:4576 sqs send-message --queue-url http://localhost:4576/queue/teste --message-body "Mensagem de teste"
{
    "MD5OfMessageBody": "4449beea32141ebd982d823daa49a542", 
    "MD5OfMessageAttributes": "d41d8cd98f00b204e9800998ecf8427e", 
    "MessageId": "e9dcd4ab-871b-4dd4-a7b7-8426a8bfb5e0"
}

Exemplo de leitura de mensagens da fila:

$ aws --endpoint-url=http://localhost:4576 sqs receive-message --queue-url http://localhost:4576/queue/teste --max-number-of-messages 10                                                              
{
    "Messages": [
        {
            "Body": "Mensagem de teste", 
            "ReceiptHandle": "e9dcd4ab-871b-4dd4-a7b7-8426a8bfb5e0#2c7aaba2-3385-459b-9dd2-d4e7fc0d6ac7", 
            "MD5OfBody": "4449beea32141ebd982d823daa49a542", 
            "MessageId": "e9dcd4ab-871b-4dd4-a7b7-8426a8bfb5e0"
        }
    ]
}

Agora já temos um ambiente com SQS montado em nossa máquina. A seguir, vamos fazer a leitura dessa fila em um projeto Java.

Criando nosso projeto para ler as mensagens

Para criar o projeto vou utilizar o mínimo de recursos possível, portanto, vamos utilizar somente a lib oficial aws sdk 2.

A seguir, o exemplo do pom:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.gabrielfeitosa</groupId>
    <artifactId>localstack-sqs-consume</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>sqs</artifactId>
            <version>2.4.8</version>
        </dependency>
    </dependencies>
</project>

E, para finalizar, segue a classe com a implementação da leitura da fila teste:

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;

import java.net.URI;

public class SqsConsume {


    public static void main(String[] args) {

        SqsClient client = SqsClient.builder()
                .region(Region.US_EAST_1)
                .endpointOverride(URI.create("http://localhost:4576"))
                .build();

        var queueUrl = "http://localhost:4576/queue/teste";

        ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl)
                .waitTimeSeconds(5)
                .maxNumberOfMessages(5)
                .build();

        while (true) {
            client.receiveMessage(receiveMessageRequest)
                    .messages()
                    .forEach( message -> {
                        System.out.println(message.body());
                    });
        }
    }
}

Bem simples, né? Não testei todos os recursos da LocalStack, mas acredito que ela pode ajudar bastante no dia a dia, dependendo do contexto em que se está.

Para os amantes de testes, eles disponibilizaram a lib localstack-utils que dá para integrar com o JUnit. No meu github disponibilizei um exemplo mais completo

Bom, por hoje é isso galera, espero que tenham gostado! Se curtiu, não deixe de compartilhar! 😉

Abraços e até a próxima.