如何使用PHP的RabbitMQ延迟消息队列?

时间:2015-08-31 17:20:59

标签: php rabbitmq php-amqplib

我正在尝试从PHP使用Delayed Message Queue用于RabbitMQ,但我的消息正在消失。

我用以下代码声明交换:

$this->channel->exchange_declare(
    'delay',
    'x-delayed-message',
    false,  /* passive, create if exchange doesn't exist */
    true,   /* durable, persist through server reboots */
    false,  /* autodelete */
    false,  /* internal */
    false,  /* nowait */
    ['x-delayed-type' => ['S', 'direct']]);

我用这段代码绑定队列:

$this->channel->queue_declare(
    $queueName,
    false,  /* Passive */
    true,   /* Durable */
    false,  /* Exclusive */
    false   /* Auto Delete */
);
$this->channel->queue_bind($queueName, "delay", $queueName);

我正在使用此代码发布消息:

$msg = new AMQPMessage(json_encode($msgData), [
    'delivery_mode' => 2,
    'x-delay' => 5000]);
$this->channel->basic_publish($msg, 'delay', $queueName);

但消息不会延迟;它仍然立即交付。我错过了什么?

3 个答案:

答案 0 :(得分:3)

来自here

消息创建应该是

require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;

$msg = new AMQPMessage($data,
            array(
                'delivery_mode' => 2, # make message persistent
                'application_headers' => new AMQPTable([
                    'x-delay' => 5000
                ])
            )
        );

答案 1 :(得分:3)

答案是针对那些需要延迟消息但又不想深入细节的人。你需要一些东西才能让它发挥作用:

安装enqueue/amqp-bunny兼容传输,例如enqueue/amqp-toolscomposer require enqueue/amqp-bunny enqueue/amqp-tools

<?php
use Enqueue\AmqpTools\RabbitMqDelayPluginDelayStrategy;
use Enqueue\AmqpBunny\AmqpConnectionFactory;

$context = (new AmqpConnectionFactory('amqp://'))->createContext();
$context->setDelayStrategy(new RabbitMqDelayPluginDelayStrategy())

$queue = $context->createQueue('foo');
$context->declareQueue($queue);

$message = $context->createMessage('Hello world!');

$context->createProducer()
    ->setDeliveryDelay(5000) // 5 sec
    ->send($queue, $message)
;

创建amqp上下文,添加延迟策略并发送延迟消息:

df.T.plot()

顺便说一句,这不是唯一可用的策略。有一个基于RabbitMQ死信队列+ ttl。它可以以相同的方式使用。

答案 2 :(得分:1)

您需要一个路由密钥才能从交换机发布到相关队列。

发布到内置直接交换的原因是因为此交换是使用路由密钥作为目标队列名称的特殊情况。

对于您创建的所有交换和队列,您需要使用路由密钥在交换和队列之间创建绑定。然后使用该路由密钥而不是目标队列名称发布消息。

我不知道创建绑定的PHP代码......但它通常看起来像这样:

channel.bind(exhange_name, queue_name, routing_key)

然后在您发布消息时:

$this->channel->basic_publish($msg, 'delay', $routing_key);