Em sistemas modernos, a necessidade de escalabilidade e processamento sob demanda é cada vez mais comum. Para lidar com grandes volumes de dados de forma eficiente, a combinação de serviços de mensageria, como o Amazon SQS, com uma plataforma de orquestração de containers, como o Amazon ECS, permite armazenar e distribuir mensagens de maneira assíncrona, garantindo que as aplicações processem as informações no seu próprio ritmo.

Neste artigo, vamos explorar como configurar essa arquitetura, utilizando o Amazon ECS Fargate para hospedar containers que escalam automaticamente com base no volume de mensagens na fila do SQS.

Requisitos

Para a realização deste laboratório, é necessário:

  • Possuir uma conta AWS.
  • Ter o AWS CLI instalado e configurado em sua máquina.

Arquitetura

Imagem da arquitetura proposta

Recursos da Arquitetura

  • Amazon SQS: Serviço de filas AWS.
  • Amazon ECS Fargate: Serviço de containers serverless.
  • AWS CloudWatch: Serviço de monitoramento e geração de métricas para autoscaling.
  • Application Auto Scaling: Serviço de gerenciamento automático de escalabilidade.

Fluxo da Arquitetura

  1. Um sistema externo ou API envia mensagens para a fila SQS.
  2. O Amazon CloudWatch monitora o número de mensagens na fila.
  3. O Application Auto Scaling ajusta dinamicamente o número de tasks no ECS Fargate com base nas métricas do CloudWatch.
  4. As tasks do ECS Fargate consomem e processam as mensagens.

Criando a Fila SQS

Com o AWS CLI configurado para sua conta, acesse o terminal e execute o comando abaixo, substituindo pela sua região AWS:

aws sqs create-queue --region  --queue-name consumer-queue-ecs-sample.fifo --attributes '{"FifoQueue":"true"}'

Saída esperada no terminal:

{
    "QueueUrl": "https://sqs..amazonaws.com//consumer-queue-ecs-sample.fifo"
}

Copie a URL da fila que foi retornada pelo terminal e armazene!

Criando e Disponibilizando a Imagem no ECR

Para exemplificar, utilizaremos um script previamente criado para consumir as mensagens da fila. Vamos iniciar?

Clonando o Repositório do GitHub

git clone https://github.com/GustavoAleixo/consumer-queue-ecs-sample.git

Acesse a pasta do repositório:

cd consumer-queue-ecs-sample

Nesta pasta encontraremos:

|_ ecs
|  |__ ecs-trust-policy.json
|  |__ task-definition.json
|_ Dockerfile
|_ index.mjs
|_ README.md
|_ .env.example

Edite o arquivo task-definition.json e substitua pelo número da sua conta AWS e pela região utilizada anteriormente na criação da fila.

Renomeie o arquivo .env.example para .env e edite-o, substituindo pela região utilizada e pela URL da fila armazenada anteriormente.

Criando a Função IAM para o ECS

O ECS precisa de permissões para acessar a fila SQS e registrar logs no CloudWatch. Execute os comandos abaixo:

aws iam create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://ecs/ecs-trust-policy.json

Agora, anexe as permissões necessárias:

aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/AmazonSQSFullAccess

Criando e Configurando o ECS

Crie um cluster ECS:

aws ecs create-cluster --cluster-name consumer-queue-ecs-sample-cluster

Depois, registre a definição da task:

aws ecs register-task-definition --cli-input-json file://ecs/task-definition.json

Crie o serviço no ECS, substituindo e pelos valores obtidos anteriormente:

aws ecs create-service \
    --cluster consumer-queue-ecs-sample-cluster \
    --service-name consumer-queue-ecs-sample-service \
    --task-definition consumer-queue-ecs-sample-task \
    --launch-type FARGATE \
    --desired-count 1 \
    --network-configuration "awsvpcConfiguration={subnets=[ID-SUBNET],securityGroups=[],assignPublicIp=ENABLED}"

Configurando Auto Scaling

aws application-autoscaling register-scalable-target \
    --service-namespace ecs \
    --scalable-dimension ecs:service:DesiredCount \
    --resource-id service/consumer-queue-ecs-sample-cluster/consumer-queue-ecs-sample-service \
    --min-capacity 0 \
    --max-capacity 10

Crie uma política de auto scaling baseada na fila:

aws application-autoscaling put-scaling-policy \
    --service-namespace ecs \
    --scalable-dimension ecs:service:DesiredCount \
    --resource-id service/consumer-queue-ecs-sample-cluster/consumer-queue-ecs-sample-service \
    --policy-name SQS-Scaling-Policy \
    --policy-type StepScaling \
    --step-scaling-policy-configuration '{"AdjustmentType": "ChangeInCapacity","StepAdjustments": [{"MetricIntervalLowerBound": 1,"ScalingAdjustment": 1}]}'

Agora, vincule a política a uma métrica do CloudWatch:

aws cloudwatch put-metric-alarm \
    --alarm-name "SQS-Messages-Alarm" \
    --metric-name ApproximateNumberOfMessagesVisible \
    --namespace AWS/SQS \
    --statistic Sum \
    --period 60 \
    --threshold 1 \
    --comparison-operator GreaterThanOrEqualToThreshold \
    --dimensions Name=QueueName,Value=consumer-queue-ecs-sample.fifo \
    --evaluation-periods 1 \
    --alarm-actions  \
    --unit Count

Tudo pronto!!! 🚀

Testando o Auto Scaling

Agora que todos os componentes foram configurados, vamos validar se o Auto Scaling está funcionando corretamente.

  1. Acesse o Console da AWS e navegue até a região onde os recursos foram criados.
  2. No campo de busca, procure por ECS e selecione o serviço Amazon Elastic Container Service.

Imagem do console aws, pesquisando pelo serviço ECS

  1. No painel do ECS, clique no cluster consumer-queue-ecs-sample-cluster.
  2. Selecione o serviço consumer-queue-ecs-sample-service e clique na aba Tasks para visualizar as instâncias em execução.

Imagem do console AWS, dentro do service do ECS

Enviando Mensagens para a Fila SQS

Agora, vamos testar o comportamento do Auto Scaling enviando mensagens para a fila SQS. Abra o terminal e execute os comandos abaixo, substituindo e pelos valores correspondentes:

  1. Envie a primeira mensagem:
aws sqs send-message \
       --queue-url https://sqs..amazonaws.com//consumer-queue-ecs-sample.fifo \
       --message-body "Message of number 1" \
       --message-group-id "example" \
       --message-deduplication-id "number1"
  1. Aguarde alguns segundos e envie a segunda mensagem:
aws sqs send-message \
    --queue-url https://sqs..amazonaws.com//consumer-queue-ecs-sample.fifo \
    --message-body "Message of number 2" \
    --message-group-id "example" \
    --message-deduplication-id "number2"

Validando a Escala Automática

Após alguns instantes, volte ao console do ECS e atualize a página. Você verá novas tasks sendo iniciadas automaticamente para processar as mensagens da fila.

Imagem de duas tasks sendo executadas no console da AWS

Parabéns! 🎉 Agora, seu ambiente está configurado para escalar dinamicamente conforme a demanda.

Conclusão

Com essa arquitetura implementada, conseguimos criar um sistema que processa mensagens de forma eficiente e escalável. O Amazon ECS Fargate, aliado ao Amazon SQS e ao Application Auto Scaling, garante que nossa aplicação consiga lidar com diferentes cargas de trabalho automaticamente. Esse modelo permite otimizar recursos, reduzir custos e melhorar a eficiência do processamento de mensagens em sistemas distribuídos.