今天在查看node.js
服務日誌的時候發現amqplib
模塊報錯No channels left to allocate
。是服務沒有複用通道,創建了太多的channel
導致該問題,通過調試找到報錯的位置,在amqplib/lib/connection.js
中freshChannel
函數中報錯。
具體代碼如下:
// I use an array to keep track of the channels, rather than an
// object. The channel identifiers are numbers, and allocated by the
// connection. If I try to allocate low numbers when they are
// available (which I do, by looking from the start of the bitset),
// this ought to keep the array small, and out of 'sparse array
// storage'. I also set entries to null, rather than deleting them, in
// the expectation that the next channel allocation will fill the slot
// again rather than growing the array. See
// http://www.html5rocks.com/en/tutorials/speed/v8/
C.freshChannel = function(channel, options) {
var next = this.freeChannels.nextClearBit(1);
if (next < 0 || next > this.channelMax)
throw new Error("No channels left to allocate");
this.freeChannels.set(next);
//
此處省略多行代碼
//
};
可以看出當創建的通道大於channelMax
就會拋出該異常。而該channelMax
的值是跟rabbitmq server
協商來的。
調試在amqplib/lib/connection.js
中afterStartOk
函數,該函數用於根據服務器端傳入的數據來設置channelMax
,heartbeat
等通訊參數,函數代碼如下:
function afterStartOk(reply) {
switch (reply.id) {
case defs.ConnectionSecure:
bail(new Error(
"Wasn't expecting to have to go through secure"));
break;
case defs.ConnectionClose:
bail(new Error(fmt("Handshake terminated by server: %s",
closeMsg(reply))));
break;
case defs.ConnectionTune:
var fields = reply.fields;//服務器段返回的通訊參數
tunedOptions.frameMax =
negotiate(fields.frameMax, allFields.frameMax);
tunedOptions.channelMax =
negotiate(fields.channelMax, allFields.channelMax); //在這裏設置最大通道數
tunedOptions.heartbeat =
negotiate(fields.heartbeat, allFields.heartbeat);
send(defs.ConnectionTuneOk);
send(defs.ConnectionOpen);
expect(defs.ConnectionOpenOk, onOpenOk);
break;
default:
bail(new Error(
fmt("Expected connection.secure, connection.close, " +
"or connection.tune during handshake; got %s",
inspect(reply, false))));
break;
}
}
在我這個環境下服務器返回的最大通道數爲2047
,由此最多可以創建2047
個通道。