Do not speak Portuguese? Translate this site with Google or Bing Translator
Laravel e Fila e Mensageria com RabbitMQ

Posted on: October 24, 2024 11:17 AM

Posted by: Renato

Categories: RabbitMQ

Views: 96

RabbitMQ + Laravel

Vou abordar nesse artigo alguns conceitos de Fila e Mensageria com RabbitMQ, mas para isso vou partir do pré-suposto que você já conhece um pouco sobre o Laravel, Menssageria, Filas e também Docker.

Antes de iniciar e pormos a mão na massa, precisamos entender como funciona o RabbitMQ com o fluxo de uma mensagem.

1- Producer

O Producer é aplicação ou serviço que irá realizar o envio de uma mensagem;

2- Exchanges

A Exchanges é para onde o Producer envia a mensagem. No RabbitMQ a aplicação nunca envia a mensagem direto para fila, sempre para uma exchange e ela faz o redirecionamento para a fila específica. Uma exchange pode possuir varias filas(queues), e o ideal é que uma fila só tenha uma exchange.

3- Binding

O Binding é uma ligação ou um link entre uma fila e uma exchange.

4- Queues

As Queues são as filas onde as mensagens serão armazenadas.

5- Consumer

O Consumer é a aplicação que irá pegar a mensagem na fila e realizar seu processamento.

Tipos de Exchanges

Existem vários tipos de exchanges, e cada tipo tem uma finalidade na hora de sua concepção. A Direct, a Topic e a Fanout estão representadas na imagem abaixo. Em nosso projeto vamos utilizar apenas o tipo Direct.

  • Direct: A mensagem é roteada para as filas(queues) cuja chave de ligação corresponde exatamente à chave de roteamento da mensagem. Por exemplo, se a fila estiver vinculada à exchange com um binding key pdf_process, uma mensagem publicada na exchange com uma routing key pdf_process será roteada para essa fila(queue).
  • Fanout: O tipo de exchange fanout roteia mensagens para todas as filas vinculadas a ele.
  • Topic: O tipo de exchange topic, faz uma correspondência curinga entre a chave de roteamento e o padrão de roteamento especificado na ligação.
  • Headers: as trocas de exchanges usam os atributos do cabeçalho da mensagem para roteamento.

Criando o Projeto

  • Vamos iniciar instalando um projeto Laravel 10.x (link).
  • Depois disso você precisa instalar o Laravel Sail (link).

Agora só nos falta criar um contêiner com o RabbitMQ para nosso projeto.

Na raiz do projeto abra em seu editor de códigos(vscode) o arquivo docker-compose.yml, criado pelo Laravel-Sail, e adicione o código abaixo, mais informações sobre as imagens Dockerhub.

rabbitmq:
image: rabbitmq:3-management
container_name: 'rabbitmq'
ports:
- 5672:5672
- 15672:15672
volumes:
- ~/.docker/rabbitmq/data/:/var/lib/rabbitmq/
- ~/.docker/rabbitmq/log/:/var/log/rabbitmq
networks:
- sail

Basta startar os contêineres com o Laravel Sail e pronto o RabbitMQ estará funcionando, sendo agora possível testar em http://localhost:15672

Usuário: guest
Senha: guest

Configurando o RabbitMQ

Vou aqui já definir as nomenclaturas do que vamos configurar no RabbitMQ, ficando assim o mais objetivo e visual o possível.

Cenário 1

Exchange: pdf_events
Queue A: create_pdf_queue
Binding entre a exchange (pdf_events) e a Queue A (create_pdf_queue): pdf_create

Cenário 2

Exchange: pdf_events
Queue B: pdf_log_queue
Binding entre a exchange (pdf_events) e a Queue B (pdf_log_queue): pdf_log

Queues do RabbitMQ

Primeiro vamos criar as Queues, elas serão do tipo Classic, com os nomes create_pdf_queue e pdf_log_queue.

Exchange do RabbitMQ

Agora vamos criar a exchange, que vai ser do tipo direct e Durable, com o nome pdf_events.

Bindings do RabbitMQ

Acesse as Queues, abra a fila create_pdf_queue e vamos criar um binding entre a fila e a exchange pdf_events, ao qual vamos dar o nome pdf_create.

Agora vamos fazer a mesma coisa para a outra Queue, abra a fila pdf_log_queue e vamos criar um binding entre a fila e a exchange pdf_events, ao qual vamos dar o nome pdf_log.

Testando o Recebimento de Mensagens

Vá nas Exchanges e abra a pdf_events, aqui estará mostrando todos os bindings que essa exchange tem.

Se estiver como na imagem acima, podemos dar continuidade e publicar uma mensagem para testarmos, mas como fazemos isso?

Simples, na mesma tela da Exchange, terá um campo chamado “Publish message” (Publicar mensagem), assim vamos poder testar nossas configurações. Vou criar uma mensagem chamada “Hello World!”, e publicar na fila pdf_create.

Se olharmos nesse momento nas filas de mensagens, veremos que a create_pdf_queue, recebeu uma mensagem e que ainda não foi consumida.

Configurando Laravel

Agora vamos realmente fazer nosso projeto enviar e consumir mensagens do RabbitMQ. Existem várias maneiras de fazer o envio e consumo das mensagens, vamos para esse projeto utilizar uma rota para enviar mensagens e outra para consumir.

Primeiro precisamos instalar a biblioteca php-amqplib

composer require php-amqplib/php-amqplib

Vamos criar nossa Controller quer vai gerenciar nossa envio e consumo de mensagens com o RabbitMQ, chamado RabbitMQController, com uma função send e outra consumer, que nesse momento estão vazias.

php artisan make:controller RabbitMQController
namespace App\Http\Controllers;

class RabbitMQController extends Controller
{
public function send()
{

}

public function consumer()
{

}
}

Agora em nosso arquivo de rotas route/web.php, vamos criar as rotas de send e consumer.

use App\Http\Controllers\RabbitMQController;

Route::get('/send', [RabbitMQController::class, 'send']);
Route::get('/consumer', [RabbitMQController::class, 'consumer']);

Enviado mensagens para o RabbitMQ

Precisamos criar nossa código para envio das mensagens ao RabbitMQ, lembrando que o arquivo é app/Http/Controllers/RabbitMQController.php.

namespace App\Http\Controllers;

use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Connection\AMQPStreamConnection;

class RabbitMQController extends Controller
{
public function send()
{
$connection = new AMQPStreamConnection('rabbitmq', 5672, 'guest', 'guest');

$message = new AMQPMessage('Hello World Queue');

$channel = $connection->channel();
$channel->basic_publish($message, 'pdf_events', 'pdf_create');
$channel->basic_publish($message, 'pdf_events', 'pdf_log');

$channel->close();
$connection->close();

echo "Message published to RabbitMQ \n";
}

public function consumer()
{

}
}

Agora em seu Browser acesse http://localhost/send , e você receberá a mensagem de sucesso que colocamos no final da função send “Message published to RabbitMQ”:

E olhando no RabbitMQ nas Queues, veremos que agora temos 2 mensagens na create_pdf_queue e 1 em pdf_log_queue.

Consumindo mensagens do RabbitMQ

Agora vamos adicionar nosso condigo para consumir as mensagens que estão nas filas. Mas nesse código vamos consumir apenas as mensagens que estão na fila pdf_log_queue. Adicionei logs para que possamos ver as mensagens que recebemos e caso apresente alguma falha no processo de consumo das mensagens.

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Log;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Connection\AMQPStreamConnection;

class RabbitMQController extends Controller
{
public function send()
{
$connection = new AMQPStreamConnection('rabbitmq', 5672, 'guest', 'guest');

$message = new AMQPMessage('Hello World Queue');

$channel = $connection->channel();
$channel->basic_publish($message, 'pdf_events', 'pdf_create');
$channel->basic_publish($message, 'pdf_events', 'pdf_log');

$channel->close();
$connection->close();

echo "Message published to RabbitMQ \n";
}

public function consumer()
{
$connection = new AMQPStreamConnection('rabbitmq', 5672, 'guest', 'guest');

$channel = $connection->channel();

$callback = function ($msg) {
Log::info('[x] Received: ', [$msg->getBody()]);
};

$channel->basic_consume('pdf_log_queue', 'pdf_log_queue', false, true, false, false, $callback);

$channel->close();
$connection->close();
}
}

basic_consume

  • queue(string): O nome da fila que será consumida.
  • consumer_tag(string): Identificador que pode ser passado para identificar o consumidor no canal de conexão. Se for passado em branco o servidor criará um identificador automaticamente.
  • no_local(boolean): Quando definido como true o servidor não envia mensagens para a conexão que a publicou.
  • no_ack(boolean): Quando definido como true o servidor não espera o reconhecimento do consumidor para a mensagem. Ele entende que a mensagem foi entregue e seu processamento será bem sucedido.
  • exclusive(boolean): Quando definido como true o consumidor tem acesso exclusivo a esta fila.
  • nowait(boolean): Quando definido como true o método não vai esperar a resposta do servidor.
  • callback(callback): Função que será executado para cada mensagem consumida.
  • arguments(AMQPTable): Passa uma tabela de argumentos opcionais para o consumo.

Vamos testar para ver se nossa aplicação esta consumindo nossas mensagens, vá em seu Browser http://localhost/consumer . Você não receberá nenhuma mensagem no browser, mas você podemos ver nos logs se houve sucesso em storage/logs/laravel.log

Espero que tenham conseguido realizar cada passo com sucesso. E quem quiser verificar o que foi desenvolvido nesse artigo e algumas melhorias veja meu Github.

Fonte: https://medium.com/@saviorenato/rabbitmq-laravel-e36ebcd85543

1

Share

Donate to Site


About Author

Renato

Developer

Add a Comment
Comments 0 Comments

No comments yet! Be the first to comment

Blog Search


Categories

OUTROS (16) Variados (109) PHP (133) Laravel (171) Black Hat (3) front-end (29) linux (114) postgresql (39) Docker (28) rest (5) soap (1) webservice (6) October (1) CMS (2) node (7) backend (13) ubuntu (56) devops (25) nodejs (5) npm (3) nvm (1) git (8) firefox (1) react (7) reactnative (5) collections (1) javascript (7) reactjs (8) yarn (0) adb (1) Solid (2) blade (3) models (1) controllers (0) log (1) html (2) hardware (3) aws (14) Transcribe (2) transcription (1) google (4) ibm (1) nuance (1) PHP Swoole (5) mysql (31) macox (4) flutter (1) symfony (1) cor (1) colors (2) homeOffice (2) jobs (3) imagick (2) ec2 (1) sw (1) websocket (2) markdown (1) ckeditor (1) tecnologia (14) faceapp (1) eloquent (14) query (4) sql (40) ddd (3) nginx (9) apache (4) certbot (1) lets-encrypt (3) debian (12) liquid (1) magento (2) ruby (1) LETSENCRYPT (1) Fibonacci (1) wine (1) transaction (1) pendrive (1) boot (1) usb (1) prf (1) policia (2) federal (1) lucena (1) mongodb (4) paypal (1) payment (1) zend (1) vim (4) ciencia (6) js (1) nosql (1) java (1) JasperReports (1) phpjasper (1) covid19 (1) saude (1) athena (1) cinnamon (1) phpunit (2) binaural (1) mysqli (3) database (42) windows (6) vala (1) json (2) oracle (1) mariadb (4) dev (12) webdev (24) s3 (4) storage (1) kitematic (1) gnome (2) web (2) intel (3) piada (1) cron (2) dba (18) lumen (1) ffmpeg (2) android (2) aplicativo (1) fedora (2) shell (4) bash (3) script (3) lider (1) htm (1) csv (1) dropbox (1) db (3) combustivel (2) haru (1) presenter (1) gasolina (1) MeioAmbiente (1) Grunt (1) biologia (1) programming (22) performance (3) brain (1) smartphones (1) telefonia (1) privacidade (1) opensource (3) microg (1) iode (1) ssh (3) zsh (2) terminal (3) dracula (1) spaceship (1) mac (2) idiomas (1) laptop (2) developer (37) api (5) data (1) matematica (1) seguranca (2) 100DaysOfCode (9) hotfix (1) documentation (1) laravelphp (10) RabbitMQ (3) Elasticsearch (1) redis (2) Raspberry (4) Padrao de design (4) JQuery (1) angularjs (4) Dicas (43) Kubernetes (3) vscode (2) backup (1) angular (3) servers (2) pipelines (1) AppSec (1) DevSecOps (4) rust (1) RustLang (1) Mozilla (1) algoritimo (1) sqlite (1) Passport (2) jwt (5) security (2) translate (1) kube (2) iot (1) politica (2) bolsonaro (1) flow (1) podcast (1) Brasil (1) containers (3) traefik (1) networking (1) host (1) POO (2) microservices (2) bug (1) cqrs (1) arquitetura (3) Architecture (4) sail (3) militar (1) artigo (1) economia (1) forcas armadas (1) ffaa (1) autenticacao (2) autorizacao (2) authentication (4) authorization (3) NoCookies (1) wsl (4) memcached (1) macos (2) unix (2) kali-linux (1) linux-tools (5) apple (1) noticias (2) composer (1) rancher (1) k8s (1) escopos (1) orm (1) jenkins (4) github (5) gitlab (3) queue (1) Passwordless (1) sonarqube (1) phpswoole (1) laraveloctane (1) Swoole (1) Swoole (1) octane (1) Structurizr (1) Diagramas (1) c4 (1) c4-models (1) compactar (1) compression (1) messaging (1) restfull (1) eventdrive (1) services (1) http (1) Monolith (1) microservice (1) historia (1) educacao (1) cavalotroia (1) OOD (0) odd (1) chatgpt (1) openai (3) vicuna (1) llama (1) gpt (1) transformers (1) pytorch (1) tensorflow (1) akitando (1) ia (1) nvidia (1) agi (1) guard (1) multiple_authen (2) rpi (1) auth (1) auth (1) livros (2) ElonMusk (2) Oh My Zsh (1) Manjaro (1) BigLinux (2) ArchLinux (1) Migration (1) Error (1) Monitor (1) Filament (1) LaravelFilament (1) replication (1) phpfpm (1) cache (1) vpn (1) l2tp (1) zorin-os (1) optimization (1) scheduling (1) monitoring (2) linkedin (1) community (1) inteligencia-artificial (2) wsl2 (1) maps (1) API_KEY_GOOGLE_MAPS (1) repmgr (1) altadisponibilidade (1) banco (1) modelagemdedados (1) inteligenciadedados (4) governancadedados (1) bancodedados (2) Observability (1) picpay (1) ecommerce (1) Curisidades (1) Samurai (1) KubeCon (1) GitOps (1) Axios (1) Fetch (1) Deepin (1) vue (4) nuxt (1) PKCE (1) Oauth2 (2) webhook (1) TypeScript (1) tailwind (1) gource (2)

New Articles



Get Latest Updates by Email