RabbitMQ存储消息以交换

时间:2019-03-22 10:40:07

标签: php rabbitmq php-amqplib

我试图弄清即使没有消费者在运行,是否也可以在RabbitMQ交换中存储消息。

我(很可能是错误地)理解,要实现交换需要“持久”以及队列和消息需要带有“持久”标记来发出

'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT

我的主要目标是将所有消息存储在交换中,以便在由于某种原因而没有使用者在运行的情况下,当我启动一个时,交换中的所有消息都可以定向到绑定队列。 我声明我的交流和排队如下:

//Sender.php
public function sendToQueue(ActionMessage $message)
    {
        $headers = [
            'content-type' => 'application/json',
            'timestamp' => $message->getCreatedAt()->getTimestamp(),
            'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
        ];
        $channel = $this->connection->getChannel();
        $channel->exchange_declare($this->exchangeName, 'direct', false, true, false);
        $qMessage = new AMQPMessage(json_encode($message->toArray()), $headers);
        $channel->basic_publish($qMessage, $this->exchangeName, $message->getTopic());
        return true;
    }
//Receiver.php
public function consume($callbackFunction)
        {
            $channel = $this->messenger->getChannel();
            $channel->exchange_declare($this->exchange, 'direct', false, true, false);
            list($queueName, ,) = $channel->queue_declare('', false, true, true, false);
            $channel->queue_bind($queueName, $this->exchangeName, $this->topicAction);

            $channel->basic_consume($queueName, '', false, true, false, false, $callbackFunction);

            while (count($channel->callbacks)) {
                $channel->wait();
            }

            $channel->close();
            $this->messenger->close();
        }

我将不胜感激(即使只是放弃这个想法并在两者之间插入一些存储空间)。 谢谢。

1 个答案:

答案 0 :(得分:0)

交换不存储消息,这是队列的工作。您遇到的问题不是没有消费者在运行,而是没有队列存在,因为您已经离开了消费者声明自己的队列。

如果您希望消息在接收者收到之前一直保持不变,则应声明:

  • “发件人”将发布到的交易所
  • 与该交换机相连的命名队列,用于分别使用的每种消息类型(如果使用direct交换,则为每个路由密钥一个)

它们都可以在Sender脚本中声明,但是在大多数情况下,在部署应用程序时将它们声明一次更为有意义,就像对待数据库架构一样对待它们。

您可以直接附加到命名队列,然后开始接收在那里等待的消息,而不是在Receiver脚本中创建匿名队列。

这将带来的主要区别是同一路由密钥的多个使用者如何交互:

  • 连接到单个交换机的多个队列(如您现有的代码一样)为每个消息创建多个副本。如果您有不同的使用者使用相同的消息来做不同的事情,这将很有用。
  • 如上文所述,
  • 连接到单个队列的多个使用者将共享消息,每个消息实际上是由不同的使用者随机处理的。如果您有多个相同的使用者来处理大量消息,这将很有用。

您可能会发现this RabbitMQ simulator对于可视化差异很有用。

您可能会发现自己确实想要混合食物:

  • 为每个必须预见每条消息的消费者的队列预先声明,以确保在该特定消费者准备读取消息之前,存储每条消息的副本。
  • 在其他使用者中声明其他临时队列,以在收到邮件时提取一份额外副本

最后一点,RabbitMQ中有两种机制可以对无法处理的消息进行不同处理:

  • Alternate Exchange捕获将从交换机中丢弃的消息(因为没有适当的队列绑定)。
  • Dead Letter Exchange捕获将从队列中丢弃的消息(例如,因为它被使用者拒绝或达到配置的超时)。

如果您实际上不想正常处理丢失的消息,而只是想检测它们,例如,AE可能在您的示例中很有用。将它们列出在错误日志中。