Rabbitmq - php amqp破坏了管道错误

时间:2013-04-05 19:57:44

标签: php rabbitmq amqp

我正在处理一个巨大的xml文档(其中包含大约一百万个条目),然后使用rabbitmq将格式化版本导入数据库。每次发布大约200,000个条目后,我收到管道错误,而rabbitmq无法从中恢复。

  

注意错误:fwrite():发送2651字节失败,errno = 11   资源暂时不可用   [/var/www/ribbon/app/Console/Command/lib/php_amqplib/amqp.inc,line   439]

     

注意错误:fwrite():发送33个字节失败,errno = 104   连接由同行重置   [/var/www/ribbon/app/Console/Command/lib/php_amqplib/amqp.inc,line   439]

     

注意错误:fwrite():发送19个字节失败,errno = 32 Broken   管道[/var/www/ribbon/app/Console/Command/lib/php_amqplib/amqp.inc,   第439行]

这会导致节点出现故障,并且需要手动终止该进程才能从中恢复。

这些是我的课程方法: -

public function publishMessage($message) {
    if (!isset($this->conn)) {
        $this->_createNewConnectionAndChannel();
    }
    try {
        $this->ch->basic_publish(
            new AMQPMessage($message, array('content_type' => 'text/plain')), 
            $this->defaults['exchange']['name'], 
            $this->defaults['binding']['routing_key']
        );
    } catch (Exception $e) {
        echo "Caught exception : " . $e->getMessage();
        echo "Creating new connection.";
        $this->_createNewConnectionAndChannel();
        $this->publishMessage($message); // try again
    }
}

protected function _createNewConnectionAndChannel() {
    if (isset($this->conn)) {
        $this->conn->close();
    }

    if(isset($this->ch)) {
        $this->ch->close();
    }

    $this->conn = new AMQPConnection(
        $this->defaults['connection']['host'], 
        $this->defaults['connection']['port'], 
        $this->defaults['connection']['user'], 
        $this->defaults['connection']['pass']
    );
    $this->ch = $this->conn->channel();
    $this->ch->access_request($this->defaults['channel']['vhost'], false, false, true, true);
    $this->ch->basic_qos(0 , 20 , 0); // fair dispatching

    $this->ch->queue_declare(
        $this->defaults['queue']['name'],
        $this->defaults['queue']['passive'],
        $this->defaults['queue']['durable'],
        $this->defaults['queue']['exclusive'],
        $this->defaults['queue']['auto_delete']
    );

    $this->ch->exchange_declare(
        $this->defaults['exchange']['name'],
        $this->defaults['exchange']['type'],
        $this->defaults['exchange']['passive'],
        $this->defaults['exchange']['durable'],
        $this->defaults['exchange']['auto_delete']
    );

    $this->ch->queue_bind(
        $this->defaults['queue']['name'],
        $this->defaults['exchange']['name'],
        $this->defaults['binding']['routing_key']
    );
}

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:8)

确保您已在Rabbit MQ上为您的用户添加了虚拟主机访问权限。我为“/”主机创建了新用户并忘记了设置访问权限,默认情况下使用。

您可以通过管理面板yourhost:15672>管理员>点击用户>寻找“设置权限”。

P.S。我假设您的RabbitMQ服务正在运行,用户存在且密码正确。

答案 1 :(得分:3)

实际上,当您的邮件中包含大量内容并且您的消费者花费太多时间来处理一条消息时,就会出现此问题,这是对兔子的“ACK”响应并尝试使用其他消息的问题。

当我遇到这个问题时,我尝试“适应”我的消息,因为它的产品工作者和每条消息都有一些像1k产品ID,所以我改为100个产品,它运作良好。

您可以阅读有关使用检测信号检测死TCP连接的更多信息here

答案 2 :(得分:0)

当我与RabbitMQ的连接断开时,此问题发生了(原因无所谓,在我的情况下,我故意停止了RabbitMQ服务以进行一些失败测试),并且我试图通过关闭旧的连接再次重新连接到RabbitMQ连接并初始化一个新连接,但是我收到了"dataframe$`Column with a space`"错误。 我解决此问题的方法是在连接上使用Broken pipe or closed connection方法:

reconnect()
相关问题