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);
            }
        });
    }

猜你喜欢

转载自blog.csdn.net/weixin_42429718/article/details/106680582
今日推荐