Я использую сетевой сервер узла js и использую функцию socket.on ('data') для приема данных. Для анализа сообщений TCP я использую метод буфера анализа. Это использует первые 4 байта как длину TCP-сообщения, чтобы я мог читать из потока TCP и формировать отдельные команды. В целом, что происходит при высокой нагрузке, это то, что есть некоторые данные мусора, возвращаемые как часть потока TCP, что вызывает проблемы.Узел js TCP-сервер, socket.on ('data') - буфер данных содержит данные мусора при высокой нагрузке
function onConnect(client) {
var accumulatingBuffer = new Buffer(0);
var totalPacketLen = -1;
var accumulatingLen = 0;
var recvedThisTimeLen = 0;
client.on('data', function (data) {
parseBuffer(client, data, accumulatingBuffer, totalPacketLen, accumulatingLen, recvedThisTimeLen);
});
}
и здесь метод parsebuffer.
function parseBuffer(client, data, accumulatingBuffer, totalPacketLen, accumulatingLen, recvedThisTimeLen) {
recvedThisTimeLen = Buffer.byteLength(data);
var tmpBuffer = new Buffer(accumulatingLen + recvedThisTimeLen);
accumulatingBuffer.copy(tmpBuffer);
data.copy(tmpBuffer, accumulatingLen); // offset for accumulating
accumulatingBuffer = tmpBuffer;
tmpBuffer = null;
accumulatingLen = accumulatingLen + recvedThisTimeLen;
if (accumulatingLen < PACKETHEADERLEN) {
return;
} else if (accumulatingLen === PACKETHEADERLEN) {
packetHeaderLen
return;
} else {
//a packet info is available..
if (totalPacketLen < 0) {
totalPacketLen = accumulatingBuffer.readUInt32BE(0);
}
}
while (accumulatingLen >= totalPacketLen + PACKETHEADERLEN) {
var aPacketBufExceptHeader = new Buffer(totalPacketLen); // a whole packet is available...
accumulatingBuffer.copy(aPacketBufExceptHeader, 0, PACKETHEADERLEN, PACKETHEADERLEN + totalPacketLen);
////////////////////////////////////////////////////////////////////
//process packet data
var stringData = aPacketBufExceptHeader.toString();
try {
var JSONObject = JSON.parse(stringData);
handler(client, JSONObject);
var newBufRebuild = new Buffer(accumulatingBuffer.length - (totalPacketLen + PACKETHEADERLEN)); // we can reduce size of allocatin
accumulatingBuffer.copy(newBufRebuild, 0, totalPacketLen + PACKETHEADERLEN, accumulatingBuffer.length);
//init
accumulatingLen = accumulatingLen - (totalPacketLen + PACKETHEADERLEN); //totalPacketLen+4
accumulatingBuffer = newBufRebuild;
newBufRebuild = null;
totalPacketLen = -1;
//For a case in which multiple packets are transmitted at once.
if (accumulatingLen <= PACKETHEADERLEN) {
//need to get more data -> wait..
return;
} else {
totalPacketLen = accumulatingBuffer.readUInt32BE(0);
}
} catch (ex) {
console.log(ex + ' unable to process data');
return;
}
}
}
Все хорошо, пока не будет высокой симулированной нагрузки, используя кучу клиентов, быстро отправляющих сообщения. В этот момент времени внутри метода ParseBuffer первая строка «data.length» возвращает больше, чем длина данных TCP. Это приводит к сбою чтения кода как UInt32BE, которые вызывают очень высокое значение в totalpacketlength (что говорит о следующей длине пакетов). Это приводит к потере сообщений. Я что-то упускаю. Пожалуйста помоги.
Спасибо за помощь. Это был плохой надзор. –
@VivekAnandY - мне просто пришло в голову, что вы можете сделать логику 'parseBuffer() логичной, а затем вы можете просто ссылаться на локальные переменные в' onConnect() 'непосредственно (поскольку они находятся в родительской области) , – jfriend00
Это то, что я сделал сейчас, и он отлично работает. Большое спасибо за помощь. –