0Pricing
PHP Academy · Aula

Trabalhando com RabbitMQ em PHP

Publique e consuma mensagens com RabbitMQ.

Trabalhando com RabbitMQ em PHP é uma aula grátis de PHP Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.

RabbitMQ no PHP

O RabbitMQ é um intermediário que fala AMQP 0-9-1. No PHP, o cliente de referência é php-amqplib/php-amqplib (PHP puro) ou o ext-amqp baseado em C. Esta lição usa php-amqplib porque ele funciona em qualquer ambiente compatível com o Composer.

O modelo central do AMQP tem três participantes: pontos de troca recebem mensagens, associações as encaminham por chave e filas as mantêm para os consumidores. Domine isso e o restante será apenas detalhe.

Instalando o cliente

Adicione a biblioteca com o Composer. Ela precisa das extensões sockets e bcmath, ambas comuns em compilações do PHP CLI.

composer require php-amqplib/php-amqplib
# Connection target, e.g. amqp://guest:guest@localhost:5672/

O modelo de ponto de troca, fila e associação

Os produtores publicam em um ponto de troca, nunca diretamente em uma fila. O tipo de ponto de troca determina o roteamento:

  • direct — correspondência exata com a chave de roteamento.
  • topic — padrões curinga, como order.*.eu.
  • fanout — transmissão para todas as filas associadas.
  • headers — correspondência com base nos atributos dos cabeçalhos.

Uma associação conecta uma fila a um ponto de troca usando um padrão de roteamento. Desacoplar os produtores da topologia das filas é justamente o objetivo da camada de pontos de troca.

Conexão e declaração

Abra uma conexão, obtenha um canal e declare sua topologia. durable: true faz the intercâmbio/fila sobreviver à reinicialização do intermediário. As declarações são idempotentes — declarar uma entidade existente com argumentos correspondentes não faz nada.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();

$ch->exchange_declare('orders', 'topic', false, true, false);
$ch->queue_declare('orders.email', false, true, false, false);
$ch->queue_bind('orders.email', 'orders', 'order.created');

echo "Topology ready\n";
$ch->close();
$conn->close();

Publicação de uma mensagem

Envolva the corpo em uma AMQPMessage. Defina delivery_mode = 2 para tornar the mensagem persistente — uma fila durável + uma mensagem persistente é o que sobrevive a uma reinicialização (uma sem the outra não sobrevive).

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();

$payload = json_encode(['orderId' => 42, 'total' => 19.90]);
$msg = new AMQPMessage($payload, [
    'content_type'  => 'application/json',
    'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT,
    'message_id'    => bin2hex(random_bytes(8)),
]);

$ch->basic_publish($msg, 'orders', 'order.created');
echo "Published\n";
$ch->close();
$conn->close();

Consumo com confirmação manual

Registre uma função de retorno com basic_consume. Passe no_ack = false para controlar a confirmação. Confirme somente depois que o trabalho for concluído com sucesso; em caso de falha, basic_nack com reencaminhamento permite que RabbitMQ entregue a mensagem novamente.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();
$ch->basic_qos(null, 10, null); // prefetch 10

$callback = function ($msg) {
    $data = json_decode($msg->getBody(), true);
    try {
        // ... do work ...
        $msg->ack();
    } catch (\Throwable $e) {
        $msg->nack(true); // requeue
    }
};

$ch->basic_consume('orders.email', '', false, false, false, false, $callback);
while ($ch->is_consuming()) {
    $ch->wait();
}

Pré-busca e distribuição justa

Por padrão, RabbitMQ distribui mensagens em alternância circular aos consumidores sem levar em conta o quanto cada um está ocupado — um consumidor lento acumula trabalho. basic_qos(null, prefetch, null) limita the número de mensagens não confirmadas que um consumidor pode manter.

Defina a pré-busca como um número pequeno (por exemplo, 1–10) para tarefas pesadas e desiguais, para que o intermediário envie trabalho novo somente aos consumidores que tenham capacidade livre. Isso é distribuição justa.

Confirmações do publicador

basic_publish retorna imediatamente e não informa se o intermediário aceitou the mensagem. Para garantir a publicação, habilite confirmações do publicador: o intermediário envia uma confirmação assim que the mensagem é persistida ou roteada com segurança.

<?php
require 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

$conn = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$ch = $conn->channel();
$ch->confirm_select(); // enable confirms on this channel

$ch->set_ack_handler(fn($m) => print("confirmed\n"));
$ch->set_nack_handler(fn($m) => print("REJECTED\n"));

$ch->basic_publish(new AMQPMessage('hi'), 'orders', 'order.created');
$ch->wait_for_pending_acks(5.0); // block until confirmed or timeout

Encaminhamento para mensagens mortas

Configure o argumento x-dead-letter-exchange de uma fila para que mensagens rejeitadas (nack sem reencaminhamento) ou expiradas sejam encaminhadas a um DLX. Combine isso com x-delivery-limit em filas de quórum para limitar as tentativas automaticamente.

<?php
use PhpAmqpLib\Wire\AMQPTable;

$args = new AMQPTable([
    'x-dead-letter-exchange'    => 'orders.dlx',
    'x-dead-letter-routing-key' => 'order.failed',
    'x-message-ttl'             => 60000, // ms before expiry
]);
// false=passive, true=durable, false=exclusive, false=autodelete, args
$ch->queue_declare('orders.email', false, true, false, false, false, $args);
$ch->queue_declare('orders.dead', false, true, false, false);
$ch->queue_bind('orders.dead', 'orders.dlx', 'order.failed');

Execução de processos em produção

Algumas regras operacionais aprendidas a duras penas para processos PHP do RabbitMQ:

  • Execute os consumidores como processos CLI de longa duração sob um supervisor (systemd / Supervisor) que os reinicie ao serem encerrados.
  • PHP perde memória com o tempo — reinicie the processo após N mensagens ou ao atingir um limite de memória.
  • Envie sinais de atividade AMQP e trate SIGTERM para um desligamento controlado (termine the mensagem em andamento e depois pare).
  • Use filas de quórum para alta disponibilidade (HA), em vez de filas espelhadas legadas.

Desligamento controlado

As implantações enviam SIGTERM. Um processo ingênuo termina no meio da mensagem, forçando uma nova entrega. Instale um manipulador de sinais que altere um indicador; termine a mensagem atual, confirme-a e depois interrompa o loop de consumo de forma limpa. pcntl_async_signals(true) permite que PHP entregue the sinal entre as esperas do AMQP.

<?php
pcntl_async_signals(true);
$running = true;
pcntl_signal(SIGTERM, function () use (&$running) {
    $running = false; // stop after the current message
    echo "SIGTERM: draining...\n";
});

while ($running && $ch->is_consuming()) {
    try {
        $ch->wait(null, false, 5); // wakes for signals
    } catch (\PhpAmqpLib\Exception\AMQPTimeoutException $e) {
        // idle tick - loop and re-check $running
    }
}
$ch->close();
echo "Stopped cleanly\n";

Verificação rápida

Sobreviver à reinicialização do intermediário.

Recapitulação

Agora você pode criar um fluxo real do RabbitMQ em PHP:

  • Publique em um intercâmbio; roteie por meio de vinculações para filas.
  • Uma fila durável + mensagem persistente sobrevive a reinicializações.
  • Consuma com confirmação manual e ajuste basic_qos pré-busca para obter uma distribuição justa.
  • Use confirmações do publicador para envios garantidos e um DLX para mensagens problemáticas.
  • Execute os processos sob um supervisor, com sinais de atividade e desligamento controlado.

Próximo: Kafka, quando você precisar de transmissão de alto débito em vez de enfileiramento de tarefas.

Perguntas Frequentes

A aula “Trabalhando com RabbitMQ em PHP” é grátis?

Sim — o texto completo de “Trabalhando com RabbitMQ em PHP” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.

O que vou aprender em “Trabalhando com RabbitMQ em PHP”?

Publique e consuma mensagens com RabbitMQ. Você pratica PHP Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar PHP Academy?

Nenhuma experiência prévia é necessária. PHP Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Trabalhando com RabbitMQ em PHP”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de PHP Academy?

Sim. Cada aula de PHP Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Por que usar mensageria assíncrona
  2. Trabalhando com RabbitMQ em PHP
  3. Apache Kafka com PHP
  4. Construindo fluxos de trabalho orientados a eventos
← Voltar para PHP Academy