首页 > 解决方案 > RabbitMQ 阻塞状态导致挂起的发布者连接

问题描述

在将消息发布到处于阻塞状态的 rabbitmq 服务器时,我们遇到了灾难性的行为。

例如内存警报或磁盘警报会导致rabbitmq 阻止所有发布,直到警报消除。所有尝试写入的连接都必须等待。这一切都很好,但问题是我们找不到任何方法来超时这个等待。

所以产生的行为是,请求永远不会结束(或者由于 nginx 超时而超时)导致崩溃。我们可以用这段代码重现问题:

function p()
    {
        $c = new \AMQPConnection([
            'host' => 'shoprabbit',
            'port' => 5672,
            'read_timeout' => 1,
            'write_timeout' => 1,
            'connect_timeout' => 1,
            'confirm_timeout' => 1,
            'rpc_timeout' => 1,
            'login' => 'guest',
            'password' => 'guest',
            'heartbeat' => '3',
        ]);
        $c->connect();


        $ch = new \AMQPChannel($c);
        $ch->setPrefetchCount(0);

        $ex = new \AMQPExchange($ch);
        $ex->setType(AMQP_EX_TYPE_DIRECT);

        $queue = new \AMQPQueue($ch);
        $queue->setName('demo');
        $queue->setFlags(AMQP_DURABLE);
        $queue->declareQueue();
$ex->publish('empty', 'demo', AMQP_NOPARAM, ['delivery_mode' => AMQP_DURABLE]);
    }

p();

并在rabbitmq中模拟阻塞状态rabbitmqctl set_vm_memory_high_watermark 0

如您所见,在这种情况下,没有任何超时发生。Heartbeat 也不起作用,因为 php 是单线程的,并且无法关闭阻塞连接。

谁能找到解决方案?

标签: phprabbitmqphp-amqp

解决方案


推荐阅读