如何避免每个TCP连接的最大通道与amqp php,持​​久连接和php-fpm

BG *_*ian 5 php amqp rabbitmq

我只是在学习rabbitMQ而且遇到了一个问题.

使用http://pecl.php.net/package/amqp 1.4版(现在最新版)和RabbitMQ 3.3.1版.我们必须使用php5-fpm和与amqp-> pconnect()的持久连接.

过了一会儿(我想65500个请求)会出现问题,停止所有写入"

无法创建频道.连接没有剩余的开放信道插槽

"

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

降低php-fpm生命周期不是一个选项,要么通过另一个技术/库等解耦application-rabbitmq通信.

有没有简单的方法来解决这个问题?

从理论上讲,它应该是每个线程一个通道(在这种情况下是php5-fpm worker)但是如何使用这个库来实现呢?

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

$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);
Run Code Online (Sandbox Code Playgroud)

谢谢 !!

pin*_*ain 6

简短回答:不要使用具有php-amqp扩展名的持久连接并且使用常规connect()性能降级来打开连接即使在高负载(例如2k + req/sec)也不应该是显着的.

答案很长:

php-amqp extension(#define DEFAULT_CHANNELS_PER_CONNECTION 255)中,每个连接限制同时存在硬编码的最大同时打开的通道.封闭渠道在关闭后会尝试重复使用.

但是在一个物理连接中,rabbitmq-c(aka librabbitmq)还有另一个限制,最大通道数 - #define AMQP_DEFAULT_MAX_CHANNELS 0这意味着没有应用自定义限制,因此应用了协议限制.根据规范(第4.9节限制),协议限制为:

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

这是根据维基百科 Unsigned: From 0 to 65,535.在AMQP中,0从不用作通道号并被解释为错误.

因此,当您在本地关闭所有通道但未关闭时,RabbitMQ将继续通道编号序列,因此它将达到指定的上限.

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

另外,我建议你不要使用持久连接,因为它有潜在的内存泄漏,一般来说有点不稳定.有计划从php-amqp中彻底删除持久性.

  • 谢谢,但删除持久连接将请求时间增加到2-3倍,这就是为什么我们从php-amqplib转移到本机php-amqp,以使用持久连接.使用php,代码行"new AMQPConnection"甚至是30ms,现在是0.3,具有persisten和PECL扩展.我们通过将每个连接的请求数(每个php5-fpm子实例)限制为500来解决这个问题,因此我们从未在生产中达到该阈值. (2认同)