訊息任務分發與訊息ACK確認機制(PHP版)(六),ackphp

來源:互聯網
上載者:User

訊息任務分發與訊息ACK確認機制(PHP版)(六),ackphp

在前面一章介紹了在PHP中如何使用RabbitMQ,至此入門的的部分就完成了,我們內心中一定還有很多疑問:如果多個消費者消費同一個隊列怎麼辦?如果這幾個消費者分任務的權重不同怎麼辦?怎麼把同一個隊列不同層級的任務分發給不同的消費者?如果消費者異常離線怎麼辦?不要著急,後面將慢慢解開面紗。我們將結合實際的應用情境來講解更多的進階用法。

任務分發機制

設想如果把每個訊息當做一個任務,生產者把任務發布到RabbitMQ,然後Consumer接收訊息處理任務,如果我們發現一個Consumer不能完成任務處理怎麼辦呢,我們會增加Consumer的數量。由一個Consumer增加到兩個Consumer,由C變為C1和C2共同來分單工作。如果C1和C2是完全一樣的,那RabbitMQ會將任務平均分發到兩個消費者。

如下我們建立c1.php和c2.php來訂閱同一個隊列在接收到訊息後sleep1秒類比任務處理的時間。

p.php代碼,生產100條帶編號的訊息:

 '10.99.121.137', 'port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));$connection->connect() or die("Cannot connect to the broker!\n");try {        $channel = new AMQPChannel($connection);        $exchange = new AMQPExchange($channel);        $exchange->setName($exchangeName);        $exchange->setType(AMQP_EX_TYPE_DIRECT);        $exchange->setFlags(AMQP_DURABLE);        $exchange->declareExchange();        $queue = new AMQPQueue($channel);        $queue->setName($queueName);        $queue->setFlags(AMQP_DURABLE);        $queue->declareQueue();        $queue->bind($exchangeName, $routeKey);        for($i=0 ; $i<100;$i++){        $exchange->publish($message.$i,$routeKey);        var_dump("[x] Sent $message $i");        }} catch (AMQPConnectionException $e) {        var_dump($e);        exit();} $connection->disconnect();

c1.php和c2.php代碼完全一樣:

connect() or die("Cannot connect to the broker!\n");$channel = new AMQPChannel($connection);$exchange = new AMQPExchange($channel);$exchange->setName($exchangeName);$exchange->setType(AMQP_EX_TYPE_DIRECT);$exchange->setFlags(AMQP_DURABLE);$exchange->declareExchange();$queue = new AMQPQueue($channel);$queue->setName($queueName);$queue->setFlags(AMQP_DURABLE);$queue->declareQueue();$queue->bind($exchangeName, $routeKey);//阻塞模式接收訊息echo "Message:\n";while(True){        $queue->consume('processMessage');//自動ACK應答        //$queue->consume('processMessage', AMQP_AUTOACK);}$conn->disconnect();/** 消費回呼函數* 處理訊息*/function processMessage($envelope, $q) {    $msg = $envelope->getBody();    sleep(1);  //sleep1秒類比任務處理    echo $msg."\n"; //處理訊息    $q->ack($envelope->getDeliveryTag()); //手動發送ACK應答}

開啟兩個中斷視窗分別執行c1.php和c2.php指令碼。確定兩個指令碼處於訂閱狀態,然後執行p.php指令碼。

看到上面兩幅圖結果就一目瞭然了。因為兩個指令碼sleep的時間相同所以任務是完全平均分發到兩個消費者的。我們修改下c2.php指令碼的sleep時間為2秒,看下結果會怎麼樣。

可以看到c1.php指令碼共收到66條訊息,c2.php指令碼收到34條訊息,基本是按照2:1來分配。那RabbitMQ是如何來保證這樣的分發機制呢,下面看RabbitMQ是如何通過ACK確認機制來實現任務分發的。

ACK訊息確認機制

首先RabbitMQ支援訊息確認機制來本證訊息被consumer正常處理,當然也可以通過no-ack不使用確認機制。RabbitMQ預設是使用ACK確認機制的。當Consumer接收到RabbitMQ發布的訊息時需要在適當的時機發送一個ACK確認的包來告知RabbitMQ,自己接收到了訊息並成功處理。所以前面講到適當的時機建議是在處理完訊息任務後發送。正如我們之前的代碼。

    $msg = $envelope->getBody();    sleep(1);  //sleep1秒類比任務處理    echo $msg."\n"; //處理訊息    $q->ack($envelope->getDeliveryTag()); //手動發送ACK應答

那如果不發送會怎樣呢?

在RabbitMQ中有一個prefetch_count的概念,這個參數的意思是允許Consumer最多同時處理幾個任務。我的版本的RabbitMQ預設這個參數是3,也就是說如果某一個Consumer在收到訊息後沒有發送ACK確認包,RabbitMQ就會任務Consumer還在處理任務,當有3個訊息都沒有發送ACK確認包時,RabbitMQ就不會再發送訊息給該Consumer。
我們把c2.php的sleep時間改回1秒,並且注釋掉ACK確認。

    $msg = $envelope->getBody();    sleep(1);  //sleep1秒類比任務處理    echo $msg."\n"; //處理訊息    //$q->ack($envelope->getDeliveryTag()); //手動發送ACK應答

發現c2指令碼只收到三條訊息。通過WEB管理工具也可以看到有三條訊息是沒有被ACK確認的。

當然任務並不會一直卡在這裡,在這是RabbitMQ任務c2在處理這三個任務。如果c2忽然終止RabbitMQ會重新分發任務。如下我終止c2指令碼。

三條任務被重新分發到了c1。再查看下WEB管理工具,unackd已經為0

如果Consumer數量很多或者希望每個Consumer同時只處理一個任務可以通過在Consumer中設定PrefetchCount來實現更加均勻的任務分發。

$channel = new AMQPChannel($connection);$channel->setPrefetchCount(1);

如下我修改了c2的PrefetchCount為1。在WEB管理外掛程式中可以看到已經有一個Consumer的PrefetchCount為1了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.