php-rabbitmq結合rabbitmq_delayed_message_exchange實現延時隊列

#查看插件列表
rabbitmq-plugins list
#如果未安裝,則下載
wget https://dl.bintray.com/rabbitmq/community-plugins/3.7.x/rabbitmq_delayed_message_exchange/rabbitmq_delayed_message_exchange-20171201-3.7.x.zip
#解壓
unzip rabbitmq_delayed_message_exchange-20171201-3.7.x.zip
#移動到rabbitmq plugins文件夾中,本機的rabbitmq是docker容器,plugins文件夾位於/plugins
mv rabbitmq_delayed_message_exchange-20171201-3.7.x.ez ./plugins
#啓用rabbitmq_delayed_message_exchange插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
#查看插件啓用情況
rabbitmq-plugins list

重啓rabbitmq

2,php-rabbitmq(自行composer安裝)

<?php
public function initDelay($queue_name)
{
        //獲取配置
        $queue_config = $this->parseQueueConfig($queue_name);
 
        $host = $queue_config['host'];
        $port = $queue_config['port'];
        $username = $queue_config['username'];
        $password = $queue_config['password'];
        //創建連接
        $this->connection = new AMQPStreamConnection($host, $port, $username, $password);
        $this->channel = $this->connection->channel();
        $this->channel->exchange_declare(
            $queue_name,
            //exchange類型爲x-delayed-message
            'x-delayed-message',
            false,
            true,
            false,
            false,
            false,
            //此處是重點,$argument必須使用new AMQPTable()生成
            new AMQPTable([
                "x-delayed-type" => 'direct'
            ])
        );
        //隊列聲明
        $this->channel->queue_declare($queue_name, false, true, false, false);
        //隊列與exchange綁定
        $this->channel->queue_bind($queue_name, $queue_name, $queue_name);
    }
 
    //生成消息
    private function createDelayMsg($data)
    {
        $this->msg = new AMQPMessage(
            $data,
            [
                'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT,
                //此處是重點,設置延時時間,單位是毫秒 1s=1000ms,實例延遲20s
                'application_headers' => new AMQPTable([
                    'x-delay' => 20000,
                ])
            ]
        );
 
        return $this->msg;
    }
    
    //生產者發送消息,代碼中只需調用此方法發送消息即可
    public function publishDelayMsg($queue_name, $msg_data)
    {
        $this->initDelay($queue_name);
 
        $msg = $this->createDelayMsg($msg_data);
        $this->channel->basic_publish($msg, $queue_name, $queue_name);
 
        $this->channel->close();
        $this->connection->close();
    }
 
    //消費者,代碼中調用消費
    public function workerMsg($queue_name, $callback = null)
    {
        $this->init($queue_name);
 
        $this->channel->basic_qos(null, 1, null);
        $this->channel->basic_consume($queue_name, '', false, false, false, false, $callback);
 
        while (count($this->channel->callbacks)) {
            $this->channel->wait();
        }
 
        $this->channel->close();
        $this->connection->close();
    }
 
    //常駐內存 消費實例
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $queue = new QueueService();
        $queue->workerMsg('order_check', function ($msg) {
            $unique = md5(uniqid(time()));
            try {
                logger("[$unique]order check Queue Received[{$msg->body}] ");
                $orderData = json_decode($msg->body, true);
                $orderId = $orderData['id'];
                $flag = array_get($orderData, 'flag');
                $order = new OrderService();
                list($code, $errMsg,) = $order->changeOrderStatus($orderId, $flag);
                if ($code > 0) {
                    //意外錯誤重新分配
                    logger("[$unique]order check Queue Exception[{$code} {$errMsg}] ");
                    $msg->delivery_info['channel']->basic_reject($msg->delivery_info['delivery_tag'], false);
                } else {
                    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
                }
            } catch (\Exception $e) {
                //意外錯誤重新分配
                logger("[$unique]order check Queue Exception[{$e->getCode()} {$e->getMessage()}] ");
                $msg->delivery_info['channel']->basic_reject($msg->delivery_info['delivery_tag'], false);
            }
        });
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章