Для моего первого проекта node.js я создаю прокси для некоторого вывода mjpeg. Теперь некоторые клиенты не могут читать поток так же быстро, как его получает сервер, поэтому я пропускаю кадры, чтобы они могли наверстать упущенное. В настоящее время я использую событие drain объекта http.ServerResponse, более или менее похожее на приведенное ниже, но поскольку drain вызывается очень часто, мне интересно, есть ли лучший/более легкий подход (я не смог найти в документы потока с возможностью записи)
httpServer.on('request',function(request,response){
//skipped setting some headers etc.
res.socket.on('drain', function(){
res.drained = true;
res.draincounter = 0;
});
//followed by some unconditional first write (set drained to false first)
res.drained = false;
res.write(someData);
};
Теперь запись фреймов в клиент происходит так:
writeFrame = function(res,frame){
if(res.drained){
//nothing in queue, ready for new data
//first set drained to false
res.drained = false;
//and feed it more data
res.write(frame, 'binary');
} else if(res.draincounter > maxDroppedFrames){
//to many dropped frames in a row, disconnect
res.end();
} else {
res.draincounter++;
}
}
Но здесь используются настраиваемые свойства и много вызовов события слива (что может быть нормально, но с моим ограниченным опытом мне это не подходит). Вкратце мой вопрос таков:
Есть ли более эффективный способ определить, что буферы записи Writable Stream пусты?
Редактировать: После перезапуска этого проекта с узлом 0.10.18 после того, как он был закрыт и бездействовал некоторое время, что-то ужасно неправильно, так как я больше не получаю события drain (по крайней мере, не так, как описано выше). На данный момент я проверяю, находится ли res.socket.bufferSize выше определенной отметки, чтобы решить, писать кадр mjpeg или нет, draincounter все еще работает. Рекомендуемое pipe() из потоковой документации в комментарии или не решение в моем случае проблема заключается не в записи всех данных о скорости клиента, а в удалении данных, когда скорость клиента ниже исходного потока.
Может ли кто-нибудь просветить меня, как правильно обрабатывать данные о противодавлении (если это не так)?
_writeableStateупоминается здесь только как инструмент "отладки",socket.bufferSizeупоминается здесь как один из тех, на которые стоит обратить внимание. Я думаю, что выберу его, хотя игра сhighWaterMarkвсе еще в моем списке как вариант. Поскольку в случае успехаres.draincounter(или, в вашем случае,res.droppedFrames) сбрасывается на0, ему не нужно ничего такого сложного, как количество кадров в секунду. Ресурс заканчивается, когда нужно удалитьmaxDroppedFramesв строке. 27.09.2013