我只是在学习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);
谢谢!
答案 0 :(得分:6)
简短回答:不要使用php-amqp
扩展名的持久连接,并且即使在高负载(例如2k + req)下,使用常规connect()
性能降级来打开连接也不应该很重要/秒)。
答案很长:
php-amqp分机(#define DEFAULT_CHANNELS_PER_CONNECTION 255
)中的每个连接限制同时存在最多同时打开的硬编码频道。封闭渠道在关闭后会尝试重复使用。
但是在一个物理连接中rabbitmq-c (aka librabbitmq)到最大通道数还存在另一个限制 - #define AMQP_DEFAULT_MAX_CHANNELS 0
,这意味着没有应用自定义限制,因此应用了协议限制。根据规范(section 4.9 Limitations),协议限制为:
每个连接的通道数:16位通道号。
是according to wikipedia Unsigned: From 0 to 65,535
。在AMQP中,0从不用作通道号并被解释为错误。
因此,当您在本地关闭所有频道但未关闭时,RabbitMQ将继续频道编号序列,因此它将达到指定的上限。
除非关闭连接,否则没有其他方法可以摆脱此类行为。
另外,我建议你不要使用持久连接,因为它有potential memory leak,一般来说有点不稳定。有计划从php-amqp中完全删除持久性。