As palavras do momento são escalabilidade e microsserviços! Todo mundo quer ser cool e estar por dentro das inovações. Pensando nisso, venho falar um pouco sobre os message brokers (envio de mensagens entre sistemas), uma das técnicas mais utilizadas para comunicação assíncrona, utilizando o RabbitMq.
É legal também entender quais problemas essa técnica resolve e quais ele não resolve! Para saber justamente o que é prego e o que é parafuso.
O que é uma fila?
Uma fila é composta por várias mensagens que serão consumidas por alguém.
Como podemos ver em vermelho na figura 1 abaixo.
Como podemos observar ainda na figura 1, nós temos o “P” representando o produtor de mensagens e os consumidores “C” (ou Workers), consumindo as mensagens dessa fila. Até aí… tudo fácil.
O que é o RabbitMq?
É um serviço de gerenciamento de filas, com ele você pode criar usuários, filas e uma gama de outras funcionalidades. Vou demonstrar aqui de forma bem simples. Para um primeiro contato apenas.
Subindo um servidor Rabbit (utilizando Docker):
$ docker run -d --hostname my-rabbit --name some-rabbit -p 8080:15672 -p 5672:5672 rabbitmq:management-alpine
Pronto, ja podemos acessar a aplicação (user: guest/ pass: guest):
E já podemos ver o nosso servidor rodando!
Criando o primeiro Producer (Produtor de mensagens)
Vamos criar um simples script php para interagir com o nosso Rabbit, primeiro crie o arquivo composer.json com o seguinte conteúdo:
{ "require": { "php-amqplib/php-amqplib": ">=2.6.1" } }
Instale as dependências:
composer.phar install
Vamos criar o arquivo send.php com o seguinte conteúdo:
<?php require_once __DIR__ . '/vendor/autoload.php'; use PhpAmqpLib\Connection\AMQPStreamConnection; use PhpAmqpLib\Message\AMQPMessage; /** * Inicia a conexão */ $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest'); $channel = $connection->channel(); /** * Declara qual a fila que será usada */ $channel->queue_declare('hello', false, false, false, false); /** * Cria a nova mensagem */ $msg = new AMQPMessage('Ola mundo!'); /** * Envia para a fila */ $channel->basic_publish($msg, '', 'hello'); /** * Encerra conexão */ $channel->close(); $connection->close();
Logo após criarmos o arquivo receive.php
<?php require_once __DIR__ . '/vendor/autoload.php'; use PhpAmqpLib\Connection\AMQPStreamConnection; /** * Inicia a conexão */ $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest'); $channel = $connection->channel(); /** * Declara qual a fila que será usada */ $channel->queue_declare('hello', false, false, false, false); echo ' [*] Waiting for messages. To exit press CTRL+C', "\n"; /** * Função que vai receber e tratar efetivamente a mensagem */ $callback = function($msg) { echo " [x] Received ", $msg->body, "\n"; }; /** * Adiciona esse "callback" para a fila */ $channel->basic_consume('hello', '', false, true, false, false, $callback); /** * Mantem a função escutando a fila por tempo indeterminado, até que seja encerrada */ while(count($channel->callbacks)) { $channel->wait(); } $channel->close(); $connection->close();
Rodando esses dois arquivos agora, com o nosso servidor up, podemos ver a seguinte mensagem (clique na imagem para expandir):
Podemos adicionar quantos “workers” forem necessários! Veja o exemplo abaixo (clique na imagem para expandir):
Incrível não?
Essa tecnologia nos permite inúmeras possibilidades, tendo apenas 1 servidor provendo o serviço do Rabbit. Isso significa que várias aplicações podem utilizar usuários diferentes e criar filas e workers conforme a sua necessidade!
Quais os casos em que eu posso utilizar o RabbitMQ?
- Processos independentes: quando eu preciso realizar uma tarefa em paralelo mas não é necessário esperar ela terminar para continuar o meu fluxo.
- Envio de email: Caso comum de quando eu não preciso aguardar uma resposta do meu SMTP. O worker pode se encarregar disso.
- Registro de logs: Com aplicações distribuídas em N servidores, não podemos e nem devemos guardar os logs localmente no servidor. Nesse cenário a aplicação A1 envia os logs para uma fila no servidor B e o worker no servidor C irá consumir a fila e armazenará corretamente esse log. Mesmo escalando minha aplicação para A1 A2 A3, todos os logs serão armazenados no local correto.
Quando não usar o RabbitMQ?
- Processos baseados em tempo. Ex: Essa rotina deve executar sempre às 14h. Para esse problema existem outras formas de resolução.
- Grande volumes de dados: Quando eu falo em grande volume, é GRANDE volume… um servidor mínimo do rabbit consegue dar conta de pelo menos 20.000 msg/s. Isso vai depender de quão pesado é a atividade do worker. Mas mesmo para aplicações que geram bastante logs, essa taxa de mensagens é suficiente. Você deve pensar em outra solução (ex: Kafka) se a sua necessidade excede as 300.000 msg/s.
Conclusão
O serviço de mensagens pode ser um grande aliado na construção de sistemas simples e independentes, separando responsabilidades e obrigando a criação de papéis distintos.
O ponto forte do RabbitMQ é a simplicidade de utilização, junto com uma interface de gerenciamento. Por outro lado é um pouco mais custoso escalar a estrutura.
Eu já utilizo o Rabbit em produção há 3 anos em diversos projetos e não tive problemas. Aconselho todos a darem uma olhada e brincarem um pouco.
Todos os arquivos estão mencionados no texto. Divirtam-se!
Para mais aprendizados: vejam a documentação oficial no site do RabbitMQ!
Curtiu do material? Acompanhe outros posts meus no blog da KingHost.
O que você achou deste conteúdo?