Rabbitmq 如何使用amqp php、持久连接和php fpm避免每个tcp连接的最大通道数

Rabbitmq 如何使用amqp php、持久连接和php fpm避免每个tcp连接的最大通道数,rabbitmq,amqp,php,Rabbitmq,Amqp,Php,我只是在学rabbitMQ,我遇到了一个问题 使用1.4版(现在最新版本)和RabbitMQ 3.3.1。 我们必须使用php5 fpm和带有amqp->pconnect()的持久连接 过了一段时间(我猜是65500个请求),停止所有写操作时出现问题 " 无法创建通道。连接没有打开的通道插槽 剩余的 " 从我在源代码中读到的内容来看,这是因为每个tcp连接都有一个达到其最大值的自动增量通道ID。这是因为每个请求都必须使用该通道,并且无法使用相同的通道(我无法找到进入php amqp通道类以使其持

我只是在学rabbitMQ,我遇到了一个问题

使用1.4版(现在最新版本)和RabbitMQ 3.3.1。 我们必须使用php5 fpm和带有amqp->pconnect()的持久连接

过了一段时间(我猜是65500个请求),停止所有写操作时出现问题 "

无法创建通道。连接没有打开的通道插槽 剩余的

"

从我在源代码中读到的内容来看,这是因为每个tcp连接都有一个达到其最大值的自动增量通道ID。这是因为每个请求都必须使用该通道,并且无法使用相同的通道(我无法找到进入php amqp通道类以使其持久化的方法),并且脚本无法通信(使用与php对象相同的通道实例)

降低php fpm生命周期不是一个选项,或者通过另一种技术/库等来解耦应用程序rabbitmq通信

有什么简单的方法可以解决这个问题吗

理论上,每个线程应该有一个通道(本例中为php5 fpm worker),但如何使用该库实现呢

我现在使用的代码(类似)


谢谢!!

简短回答:不要在
php amqp
扩展中使用持久连接,使用常规的
connect()
打开连接时,即使在高负载(如2k+req/秒)下,性能下降也不会太大

长答案:

扩展()中的每个连接限制都有硬编码的最大同时打开的通道。关闭的通道在关闭后将尝试重新使用

但在一个物理连接内的最大通道数中还有另一个限制-,这意味着没有应用自定义限制,因此应用了协议限制。根据规范()协议限制为:

每个连接的通道数:16位通道数

无符号:从0到65535。在AMQP中,0从不用作通道号,并解释为错误

所以,当您在本地关闭所有通道但不关闭时,RabbitMQ将继续通道编号顺序,从而达到指定的上限

除非关闭您的连接,否则没有其他方法可以摆脱这种行为


另外,我建议您完全不要使用持久性连接,因为它已经使用了,而且通常有点不稳定。有计划从php amqp中完全删除持久性。

谢谢,但是删除持久性连接会将请求时间增加到2-3倍,这就是为什么我们从php amqplib迁移到本机php amqp的原因e持久连接。php的代码行“new AMQPConnection”甚至是30ms,现在persisten和PECL扩展的代码行是0.3。我们通过限制每个连接(每个php5 fpm子实例)的请求数来解决这个问题如果性能确实存在问题,您可以在Php和RabbitMQ之间使用一些东西,例如可以侦听UDP或TCP简单连接并转发到RabbitMQ的Logstash。您好,新的默认值似乎是2048个通道(除非在连接上另有设置)
$this->con = new AMQPConnection(array(
    'host'          => $this->con_params['host'],
    'port'          => $this->con_params['port'],
    'vhost'         => $this->con_params['vhost'],
    'login'         => $this->con_params['user'],
    'password'      => $this->con_params['pass'],
    'read_timeout'  => 1,//seconds
    'write_timeout' => 1,//seconds
'connect_timeout' => 1,//seconds
));
$this->con->pconnect();
$channel = new AMQPChannel($this->con);
$queue = new AMQPQueue($channel);
$queue->setName($queueName);
$queue->setFlags(AMQP_DURABLE);
//$queue->declareQueue();//make sure it exists
$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setFlags(AMQP_DURABLE);
$exchange->setType(AMQP_EX_TYPE_DIRECT);
//$exchange->declareExchange();
$this->queues[$queueName]->bind($exchangeName);