Php RabbitMQ在exchange中存储消息

Php RabbitMQ在exchange中存储消息,php,rabbitmq,php-amqplib,Php,Rabbitmq,Php Amqplib,我试图弄清楚,即使在没有使用者运行的情况下,是否可以在RabbitMQ交换中存储消息 我理解(可能是错误的)为了实现交换需要是“持久的”,队列和消息需要使用“持久的”标志发送出去 我的主要目标是将所有消息存储在exchange中,这样,无论出于何种原因,当我启动一个时,exchange中的所有消息都可以定向到绑定队列。 我声明我的交换和队列如下: //Sender.php public function sendToQueue(ActionMessage $message) {

我试图弄清楚,即使在没有使用者运行的情况下,是否可以在RabbitMQ交换中存储消息

我理解(可能是错误的)为了实现交换需要是“持久的”,队列和消息需要使用“持久的”标志发送出去

我的主要目标是将所有消息存储在exchange中,这样,无论出于何种原因,当我启动一个时,exchange中的所有消息都可以定向到绑定队列。 我声明我的交换和队列如下:

//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();
        }
我将感谢任何帮助(即使只是放弃这个想法并在两者之间插入一些存储)。
谢谢。

exchange不存储邮件,这是队列的工作。您遇到的问题不是没有消费者在运行,而是不存在队列,因为您让消费者声明他们自己的队列

如果希望消息在消费者拾取之前保持不变,则应声明:

  • “发件人”将发布到的exchange
  • 附加到该交换的指定队列,用于将单独使用的每种类型的消息(如果使用
    direct
    exchange,则每个路由密钥一个)
它们都可以在发送方脚本中声明,但在大多数情况下,在部署应用程序时声明它们一次更为合理,就像对待数据库模式一样

不必在接收方脚本中创建匿名队列,您只需附加到命名队列,并开始接收在那里等待的消息

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

  • 与现有代码一样,连接到单个exchange的多个队列会创建每条邮件的多个副本。如果不同的消费者使用相同的消息做不同的事情,这将非常有用
  • 如上所述,连接到单个队列的多个使用者将共享消息,每个使用者基本上是随机地由不同的使用者处理的。如果您有多个相同的使用者来处理大量消息,这将非常有用
您可能会发现将差异可视化很有用

你可能会发现你实际上想要一种混合物:

  • 为必须查看每条消息的每个使用者预先声明一个队列,以确保存储每条消息的副本,直到该特定使用者准备好读取它为止
  • 在其他使用者中声明其他临时队列,以便在消息传入时获取额外的消息副本
最后请注意,RabbitMQ中有两种机制可用于对无法处理的消息进行不同的处理:

  • 捕获将从exchange中丢弃的消息(因为没有适当的队列绑定)
  • 捕获将从队列中丢弃的消息(例如,由于消费者拒绝或达到配置的超时)

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

RabbitMQ exchange
-我想您的意思是
队列
交换是一种传递方式,如
主题
扇出
等。。传递信息的一种方式。如果您使队列持久,无需自动删除并要求确认,则可以在没有消费者的情况下将消息放入其中。如果您具有自动删除功能,则在没有消费者的情况下删除队列。如果您没有确认功能,则消息将在队列中直接发送,而无需等待。(耐用可能是可选的,但这不是一个坏主意)。这只是我的想法,但我很确定,如果这些设置错误,出于明显的原因,它们会引起问题。对于exchange可能也是如此,但我从未尝试在exchange中“保留”消息。我所做的一件事是,我的所有工作人员都会获得一个带有扇出exchange的额外(自动删除/无确认)队列,我使用该队列向工作人员发送命令消息。例如,我可以向他们发送一个命令
consume:queue\u name
,他们就会这样做。这也为他们提供了一个默认的队列,以及告诉他们新队列的方法。基本上,每当客户机占用一个作业时,它就会进入一个特定于它们的队列,主要是为了防止它们占用所有的工作人员,因为它们的所有消息都进入一个队列,只是为了它们。然后工人们就开始循环。等等。这样它就有机地防止了这种情况。@ArtisticPhoenix非常感谢,我来检查一下。
//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();
        }