Criando um background job com RabbitMQ e Sneakers no Rails
/ 7 min read
Introdução
Um dos serviços mais utilizados no Rails de background jobs é o Sidekiq, recentemente descobrir uma excelente alternativa chamada Sneakers. Sneakers é um serviço de execução de tarefas em backgroud que utiliza o RabbitMQ para realizar a execução de tarefas, nesse post veremos como implementar e quais as vantagens de se utilizá-la.
Características do Sneakers
- Tem um processamento de jobs em backgroud de alta performance e disponibilidade;
- Usa o modelo de execução híbrida onde muitos processos são gerados (como o Unicorn) e muitas threads são usadas por processo (como Puma), para que todos os seus núcleos atinjam o máximo e tenha o melhor dos dois mundos;
- Executa mais de 1000 req/s;
- Possui uma estrutura de processamento altamente disponível (tendo as mesmas garantias que o RabbitMQ oferece);
- Possui uma DSL/API familiar que também suporta semânticas avançadas de mensagens, como rejeitar, reenfileirar, reconhecer, etc.
Requisitos Necessários
Para configuração e execução do projeto será necessário atender aos seguintes requisitos:
- Ter o docker instalado;
- Ter Rails na versão ≥ 6;
- Ter o ruby na versão ≥ 3
- Sneakers na versão ≥ 2.11.0
Instalação do RabbitMQ
O RabbitMQ será utilizado para armazenar as informações (mensagens) que serão processados pelos works da nossa aplicação, para isso vamos usar o docker para baixar uma imagem já pronta para utilizarmos no projeto.
Crie uma pasta chamada rabbitmq-work
e dentro desta pasta criei o arquivo docker-compose.yml
com o
seguinte conteúdo:
depois rode o comando:
o docker irá baixar a imagem do rabbitmq e subir o container, para acessar o sistema de administração do rabbitmq é necessário habilitar o gerenciamento de plugins com o comando:
o comando acima deve ser executado no terminal dentro do container do rabbitmq uma das maneiras de fazer
isso é usar o plugin de gerenciamento do docker do VS Code instale em seu Visual Code utilizando o menu de
extensions
clique no menu do docker então clique com o botão direito no container do rabbitmq e clique em Attach Shell
será aberto o terminal dentro do container
então execute o comando:
veja como fica na imagem abaixo:
execute:
Pronto com o rabbitmq_management habilitado é possível acessar
http://localhost:15672
usando o login e a senha rabbitmq
Implementação da aplicação BackgroundJob
Dependências:
Ruby 3.3.0
Rails 6.1.7.9
Entre na pasta rabbitmq-work e rode:
após a aplicação ser criada com sucesso adicione o sneakers
ao gemfile do rails
depois dentro da pasta da aplicação crie o arquivo /config/initializers/sneakers.rb
com o seguinte conteúdo:
Aqui está uma explicação detalhada sobre essas configurações:
Esta linha importa a classe LoggingMetrics do módulo Sneakers::Metrics, que será usada para registrar métricas.
Esta configuração define vários parâmetros para o funcionamento do Sneakers:
- amqp: URL de conexão com o RabbitMQ.
- metrics: Instância de LoggingMetrics para registrar métricas.
- workers: Número de processos por CPU.
- threads: Tamanho do pool de threads.
- prefetch: Número de jobs que serão pré-carregados.
- durable: Define se a fila é durável.
- ack: Define se é necessário reconhecimento (acknowledgment).
- heartbeat: Intervalo de heartbeat para manter a conexão com o broker.
- env: Ambiente de execução (neste caso, ‘development’).
Estas linhas configuram o logger do Sneakers para usar o logger do Rails e definem o nível de log para INFO.
Este código é essencial para integrar o processamento de filas com RabbitMQ na aplicação, garantindo que as tarefas sejam gerenciadas de forma eficiente e que as métricas e logs sejam devidamente registrados.
após isso crie a pasta /app/workers
e crie o arquivo /app/workers/profiling_worker.rb
com o código a
seguir:
O código acima define uma classe ProfilingWorker que utiliza a biblioteca Sneakers para processar mensagens de uma fila RabbitMQ. Este worker é configurado para processar mensagens da fila ‘downloads’, registrar o conteúdo da mensagem e reconhecer a mensagem como processada. Se ocorrer um erro durante o processamento, o erro será registrado.
Aqui está uma explicação detalhada do código:
- A classe
ProfilingWorker
inclui o móduloSneakers::Worker
, o que a transforma em um worker que pode processar mensagens de uma fila RabbitMQ.
- O método
from_queue
configura o worker para consumir mensagens da fila chamadadownloads
. - exchange:
download_process
especifica o exchange RabbitMQ associado à fila. - timeout_job_after: 1 define um tempo limite de 1 segundo para o processamento de cada mensagem.
- O método
work
é chamado para processar cada mensagem recebida da fila. logger.info JSON.parse(message)
registra a mensagem recebida após convertê-la de JSON para um objeto Ruby.ack!
reconhece a mensagem, informando ao RabbitMQ que foi processada com sucesso.- O bloco
rescue
captura qualquer exceção (StandardError) que ocorra durante o processamento da mensagem.logger.error
e registra o erro ocorrido.
Depois adicione o código
ao arquivo /Rakefile
rode o comando:
abra o admin do RabbitMQ
e acesse a área onde fica as filas, procure a fila downloads
e publique a
mensagem abaixo:
Ao executar a mensagem acima a saída no console da aplicação deverá ser como é mostrado na imagem abaixo.
no log registra-se quando o worker inicia, quanto tempo levou para ser executado, informa que o ACK foi enviado para o RabbitMQ e quando o work finaliza.
Fluxo de Execução de Works
Abaixo é exibido de forma visual como um work funciona. Quando se executa o comando rake sneakers:run
o work ProfillingWorker irá ser iniciado e ficará escutando a fila downloads
ele irá executar qualquer mensagem
que seja enviado para essa fila. Do outro lado podemos ter uma ou várias aplicações que enviam mensagens para
a fila de download
, o que é interessante de se vê no fluxo é que as aplicações que produzem dados para o
worker podem ser implementadas em diferentes linguagens.
Github
https://github.com/edivandecastro/rabbitmq-work/commit/a913fd2295417b86805da5df55197d6862e796de