Producer confirm of PHP actual combat rabbitmq

Time:2021-7-30

brief introduction

In order to improve the high availability of the system, the producer is sendingmessageNeed to passMQreplyACKTo ensuremessageSuccessfully stored.

Producer confirm of PHP actual combat rabbitmq

Note: WeChat official account: Architect’s Road

RabbitMQPublisher confirms is introduced on the official website. UnfortunatelyexampleNo codephpVersion, andphp-amqplibIt is also a group of volunteers who have limited energy in maintenance and do not use example completely
Producer confirm of PHP actual combat rabbitmq

php-amqblibSome developers mentioned itIssuesHope to improveexample
https://github.com/php-amqpli…

This article will use PHP to implement itPublisher Confirms, hope to help you, the code has been submitted togithub:https://github.com/jiaoyang3/…

Several strategies

affair

Transactions can guarantee the atomic operation rabbitmq, which is also very simple to use.

$channel->tx_select();//begin trx
$channel->tx_commit();//commit trx
$channel->tx_rollback();//rollback

testexampleNo, found after runningmessageSubmit toqueue

<?php

require_once '../../vendor/autoload.php';

use PhpAmqpLib\Message\AMQPMessage;
use RabbitMQ\RabbitMQ;

try {
    $rabbit  = new RabbitMQ();
    $channel = $rabbit->getChannel();
    $channel->tx_select();//begin trx

    $queueName = 'test-single-queue2';
    $rabbit->createQueue($queueName, false, true, false, false);

    for ($i = 0; $i < 10000; $i++) {
        $rabbit->sendMessage($i . "this is a test message.", $queueName, '', [
            'delivery_ mode' => AMQPMessage::DELIVERY_ MODE_ Persistent // the message is persisted. Restart rabbitmq and the message will not be lost
        ]);
        if ($i == 10) {
            throw new Exception('rollbock');
        }
    }
    $channel->tx_commit();//commit trx
    unset($rabbit);//close
} catch (Exception $e) {
    $channel->tx_rollback();//rollback
    echo $e->getMessage();
}

Single ACK

Every time the producer sends onemessageMQThe service will persist the outgoing data and reply after successful storageack/nackMessage to producer.

Enable confirm

$channel->confirm_select();

Register ACK / NACK fallback method

//ack callback function
$channel->set_ack_handler(function (AMQPMessage $message){
    echo 'ack' . $message->getBody() . PHP_EOL;
});
//nack callback function
$channel->set_nack_handler(function (AMQPMessage $message){
    echo 'ack' . $message->getBody() .PHP_EOL;
});

set upack/nackTimeout

    $channel->wait_for_pending_acks_returns(5);//set wait time

The test code is as follows. The complete code can be accessed to GitHub

<?php

require_once '../../vendor/autoload.php';

use PhpAmqpLib\Message\AMQPMessage;
use RabbitMQ\RabbitMQ;


$rabbit  = new RabbitMQ();
$channel = $rabbit->getChannel();
$channel->confirm_select();//open confirm
//ack callback function
$channel->set_ack_handler(function (AMQPMessage $message){
    echo 'ack' . $message->getBody() . PHP_EOL;
});
//nack callback function
$channel->set_nack_handler(function (AMQPMessage $message){
    echo 'ack' . $message->getBody() .PHP_EOL;
});

$queueName = 'test-single-queue1';
$rabbit->createQueue($queueName, false, true, false, false);

for ($i = 0; $i < 10000; $i++) {
    $message = $i . "this is a test message.";
    $rabbit->sendMessage($message, $queueName, '', [
        'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
    ]);
    echo $message . '  has been sent' . PHP_EOL;
    $channel->wait_for_pending_acks_returns(5);//set wait time
    sleep(1);
}

unset($rabbit);// Close connection

Multiple ACK

EachmessageallackLow performance
Batch hereack, set every 50messagefocusack, the code is also very simple

<?php

require_once '../../vendor/autoload.php';

use PhpAmqpLib\Message\AMQPMessage;
use RabbitMQ\RabbitMQ;


$rabbit  = new RabbitMQ();
$channel = $rabbit->getChannel();
$channel->confirm_select();//open confirm
//ack callback function
$channel->set_ack_handler(function (AMQPMessage $message){
    echo 'ack' . $message->getBody() . PHP_EOL;
});
//nack callback function
$channel->set_nack_handler(function (AMQPMessage $message){
    echo 'ack' . $message->getBody() .PHP_EOL;
});


$queueName = 'test-single-queue';
$rabbit->createQueue($queueName, false, true, false, false);

//The performance of ACK is very low every time. Batch ack is set every 50 messages
$batchSize               = 50;
$outstandingMessageCount = 0;
for ($i = 0; $i < 10000; $i++) {
    $message = $i . "this is a test message.";
    $rabbit->sendMessage($message, $queueName, '', [
        'delivery_ mode' => AMQPMessage::DELIVERY_ MODE_ Persistent // the message is persisted. Restart rabbitmq and the message will not be lost
    ]);
    Echo $message. 'sent'. PHP_ EOL;
    if (++$outstandingMessageCount == $batchSize) {
        echo '------';
        $channel->wait_for_pending_acks_returns(5);
        $outstandingMessageCount = 0;
    }
    sleep(1);
}
if ($outstandingMessageCount > 0) {
    $channel->wait_for_pending_acks_returns(5);
}

unset($rabbit);// Close connection

Asynchronous ACK

There is no doubt that the efficiency of asynchrony is the highest. Unfortunately, it is not foundphp-amqplibNo, the more people use a language, the better the ecology,phpIt’s gone.