I'm trying to figure out whether is possible to store messages in a RabbitMQ exchange even when there's no consumer running.
I understood (probably incorrectly) that to achieve that the exchange needs to be "durable" as well as the queue and the message needs to be sent out with the "persistent" flag
'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
My main goal is to store all the messages in the exchange so that, in the case that for whatever reason no consumer is running, when I launch one all the messages in the exchange can get directed to the bonded queue. I'm declaring my exchanges and queue as follows:
//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();
}
I'll appreciate any help (even just to discard the idea and insert some storage in between). Thanks.
An exchange does not store messages, that is the job of a queue. The problem you're having is not that no consumers are running, but that no queues exist, because you have left the consumers to declare their own queues.
If you want the messages to be persistent until a consumer picks them up, you should declare:
direct
exchange) These can both be declared in the Sender script, but in most cases it makes more sense to declare them once when the application is deployed, treating them like you would a database schema.
Instead of creating an anonymous queue in the Receiver script, you can then just attach to the named queue, and start receiving the messages waiting there.
The main difference this will make is how multiple consumers for the same routing key will interact:
You might find this RabbitMQ simulator useful to visualise the difference.
You might find you actually want a mixture:
As a final note, there are two mechanisms in RabbitMQ for falling back to different processing for messages that can't be processed:
An AE might be useful in your example if you don't actually want to process the missed messages normally, you just want to detect them, eg listing them in an error log.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.