WedX - журнал о программировании и компьютерных науках

Определить, имеет ли http.ServerResponse/Writable Stream пустую очередь записи

Для моего первого проекта 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() из потоковой документации в комментарии или не решение в моем случае проблема заключается не в записи всех данных о скорости клиента, а в удалении данных, когда скорость клиента ниже исходного потока.

Может ли кто-нибудь просветить меня, как правильно обрабатывать данные о противодавлении (если это не так)?

08.11.2012

  • Если вы еще этого не сделали, загляните в stream-handbook подстека. 09.11.2012
  • Действительно хороший ресурс, вчера пришлось найти большую часть из-за ошибки конца пути, мог бы использовать его тогда меня немного беспокоит: Примечание: API для обработки противодавления существенно изменится в будущих версиях узла => есть идеи, что это такое/будет? 09.11.2012
  • Да, я подумал, что тебе понравится эта часть. ;) Твоя догадка так же хороша как и моя. 09.11.2012

Ответы:


1

Лично я бы проверил res._writableState напрямую, но на данный момент вы погружаетесь в исходный код узла, который может быть изменен, но я сомневаюсь, что многое из этого изменится в будущем.

но тогда это когда вещи становятся искусством. есть так много разных флагов, которые вы можете проверить: https://github.com/joyent/node/blob/master/lib/_stream_writable.js#L40

если вы хотите проверить текущий размер буфера, вы можете проверить res._writableState.length - https://github.com/joyent/node/blob/master/lib/_stream_writable.js#L79.

это будет писаться только в том случае, если буфер равен 0.

function writeFrame(res, frame) {
  if (res._writableState.length) {
    if (++res.droppedFrames > maxDroppedFrames) res.end()
  } else {
    res.write(frame)
  }
}

если вы хотите писать только тогда, когда буфер ниже верхней отметки (т.е. ему не нужен слив), вы можете просто проверить res._writableState.needDrain - https://github.com/joyent/node/blob/master/lib/_stream_writable.js#L57

это будет писаться только в том случае, если буфер ниже верхней отметки:

function writeFrame(res, frame) {
  if (res._writableState.needDrain) {
    if (++res.droppedFrames > maxDroppedFrames) res.end()
  } else {
    res.write(frame)
  }
}

есть и другие флаги, которые могут вас заинтересовать. суть в том, что вам не нужно прослушивать какие-либо события drain или выполнять какую-либо внутреннюю пометку состояния.

примечание: вам, вероятно, следует заботиться только о maxDroppedFrames / second, а не об абсолютном общем числе. вы также не должны писать с кодировкой binary, вместо этого просто записывайте необработанный буфер.

Кроме того, это, вероятно, работает только в узле 0.10+

20.09.2013
  • Хм, _writeableState упоминается здесь только как инструмент "отладки", socket.bufferSize упоминается здесь как один из тех, на которые стоит обратить внимание. Я думаю, что выберу его, хотя игра с highWaterMark все еще в моем списке как вариант. Поскольку в случае успеха res.draincounter (или, в вашем случае, res.droppedFrames) сбрасывается на 0, ему не нужно ничего такого сложного, как количество кадров в секунду. Ресурс заканчивается, когда нужно удалить maxDroppedFrames в строке. 27.09.2013
  • Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]