简体   繁体   English

如何从AMQP(RabbitMQ)队列中删除消息?

[英]How delete messages from an AMQP (RabbitMQ) queue?

This is the thing. 这就是事情。

I am reading results queue from Rabbitmq using PHP AMQP in order to process vital information on every email sent. 我正在使用PHP AMQP从Rabbitmq读取结果队列,以便处理每封发送的电子邮件的重要信息。 After this is done, i need to delete or mark that message as written so the next time i read the queue i don't get the messages already processed. 完成此操作后,我需要删除或标记该消息,因此下次我读取队列时,我不会收到已处理的消息。

As the Rabbitmq server is sending over 10.000 emails an hour, every time i read the queue to process result sendings, the script can be running for at lease 5 minutes in order to process all messages in the queue, so after it is done, several hundred of new messages were places during those 5 minutes. 由于Rabbitmq服务器每小时发送超过10,000封电子邮件,每次我读取队列以处理结果发送时,脚本可以运行至少5分钟,以便处理队列中的所有消息,因此在完成后,几个在这5分钟内,有数百条新消息被放置。 That makes impossible for me to purge the queue after script finishes because it would delete messages places during the script running which where not processed. 这使我无法在脚本完成后清除队列,因为它会在脚本运行期间删除未处理的消息。

That leaves me with only one choice. 这让我只有一个选择。 Mark or delete a message just after being processed or read by my AMQP script. 在我的AMQP脚本处理或读取之后标记或删除消息。

Is there a way to do that? 有没有办法做到这一点? (here is the script) (这是脚本)

<?php
/**
 *  result.php
 *  Script that connects to RabbitMQ, and takes the result message from
 *  the result message queue.
 */

// include the settings
 require_once('settings.php');

// try to set up a connection to the RabbitMQ server
try
{
    // construct the connection to the RabbitMQ server
    $connection = new AMQPConnection(array(
        'host'      =>  $hostname,
        'login'     =>  $username,
        'password'  =>  $password,
        'vhost'     =>  $vhost
    ));

    // connect to the RabbitMQ server
    $connection->connect();
}
catch (AMQPException $exception)
{
    echo "Could not establish a connection to the RabbitMQ server.\n";
}

// try to create the channel
try
{
    // open the channel
    $channel = new AMQPChannel($connection);
}
catch (AMQPConnectionException $exception)
{
    echo "Connection to the broker was lost (creating channel).\n";
}

// try to create the queue
try
{
    // create the queue and bind the exchange
    $queue   = new AMQPQueue($channel);
    $queue->setName($resultbox);
    $queue->setFlags(AMQP_DURABLE);
    $queue->bind('exchange1', 'key1');
    $queue->declare();
}
catch (AMQPQueueException $exception)
{
    echo "Channel is not connected to a broker (creating queue).\n";
}
catch (AMQPConnectionException $exception)
{
    echo "Connection to the broker was lost. (creating queue)/\n";
}

// Get the message from the queue. 
while ($envelope = $queue->get()) {
    //Function that processes the message
    process_message($envelope->getBody());
}
    $queue->purge();

// done, close the connection to RabbitMQ
$connection->disconnect();
?>

Acknowledge message(s) $queue->ack() after successful processing or even consume/get them with AMQP_AUTOACK flag. 成功处理后确认消息$queue->ack()甚至使用AMQP_AUTOACK标志消耗/获取AMQP_AUTOACK

UPD: UPD:

Based on your code: 根据您的代码:

1. Ack'ing message 1.确认消息
while ($envelope = $queue->get(AMQP_AUTOACK)) {
    //Function that processes the message
    process_message($envelope->getBody());
}
2. Getting it with AMQP_AUTOACK flag: 2.获取AMQP_AUTOACK标志:
$queue->consume(function ($envelope, $queue) {
        process_message($envelope->getBody());
        $queue->ack($envelope->getDeliveryTag());
});

PS: PS:

Check AMQPQueue::consume documentation, looks like it is more suitable here. 检查AMQPQueue :: consume文档,看起来更合适。

3. You can consume and ack message after it been processed: 3.处理后可以使用消息和确认消息:
 $queue->consume(function ($envelope, $queue) { process_message($envelope->getBody()); $queue->ack($envelope->getDeliveryTag()); }); 
4. or consume with AMQP_AUTOACK flag, but when procesing fails you won't be able to process message again: 4.或使用AMQP_AUTOACK标志,但当处理失败时,您将无法再次处理消息:
 $queue->consume(function ($envelope, $queue) { process_message($envelope->getBody()); $queue->ack($envelope->getDeliveryTag()); }, AMQP_AUTOACK); 

Conclusion: I would recommend to use #3 solution, but it's up to you. 结论:我建议使用#3解决方案,但这取决于你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM