nodejs http response.write: возможно ли нехватка памяти?

Если у меня есть следующий код для повторной отправки данных клиенту каждые 10 мс:

setInterval(function() {
    res.write(somedata);
}, 10ms);

Что произойдет, если клиент очень медленно получает данные?

Будет ли на сервере ошибка нехватки памяти?

Редактировать: на самом деле соединение остается в живых, отправлять бесконечные jpeg-данные (HTTP multipart/x-mixed-replace header + body + header + body.....)
Поскольку node.js response.write является асинхронным,
поэтому некоторые пользователи предполагают, что он может хранить данные во внутреннем буфере и ждать, пока нижний уровень не скажет, что может отправлять,
так внутренний буфер будет расти, я прав?

Если я прав, то как это решить?
проблема в том, что node.js не уведомляет меня, когда данные отправляются для одного вызова записи.

Другими словами, я не могу сказать пользователю, что таким образом теоретически нет риска "нехватки памяти" и как это исправить.


Обновление: по ключевому слову "сток", указанному пользователем user568109, я изучил источник файла node.js и получил заключение:
это действительно приведет к ошибке "недостаточно памяти". Я должен проверить возвращаемое значение response.write(...)===false и затем обработать событие "утечки" ответа.

http.js:

OutgoingMessage.prototype._buffer = function(data, encoding) {
  this.output.push(data); //-------------No check here, will cause "out-of-memory"
  this.outputEncodings.push(encoding);

  return false;
};


OutgoingMessage.prototype._writeRaw = function(data, encoding) { //this will be called by resonse.write
  if (data.length === 0) {
    return true;
  }

  if (this.connection &&
      this.connection._httpMessage === this &&
      this.connection.writable &&
      !this.connection.destroyed) {
    // There might be pending data in the this.output buffer.
    while (this.output.length) {
      if (!this.connection.writable) {    //when not ready to send
        this._buffer(data, encoding);    //----------> save data into internal buffer
        return false;
      }
      var c = this.output.shift();
      var e = this.outputEncodings.shift();
      this.connection.write(c, e);
    }

    // Directly write to socket.
    return this.connection.write(data, encoding);
  } else if (this.connection && this.connection.destroyed) {
    // The socket was destroyed.  If we're still trying to write to it,
    // then we haven't gotten the 'close' event yet.
    return false;
  } else {
    // buffer, as long as we're not destroyed.
    this._buffer(data, encoding);
    return false;
  }
};

1 ответ

Решение

Некоторые ошибки:

  1. При отправке через http это не будет хорошей идеей. Браузер может считать запрос тайм-аутом, если он не завершен в течение указанного периода времени. Сервер тоже закроет соединение, которое простаивает слишком долго. Если клиент не успевает, время ожидания почти определено.

  2. setInterval для 10ms также подвержен некоторым ограничениям. Это не значит, что он будет повторяться через каждые 10 мсек, 10 мсек - это минимум, который он будет ждать перед повторением. Это будет медленнее, чем вы установите интервал.

  3. Допустим, у вас есть шанс перегрузить ответ данными, тогда в какой-то момент сервер завершит соединение и ответит 413 Request Entity Too Large в зависимости от того, какой лимит установлен.

  4. Node.js имеет однопоточную архитектуру с максимальным ограничением памяти около 1,7 ГБ. Если вы установите слишком высокий лимит серверов и будете иметь много входящих подключений, вы получите process out of memory ошибка.

Таким образом, с соответствующими ограничениями он либо выдаст таймаут, либо будет слишком большим запросом (И нет других ошибок в вашей программе.)

Обновить

Вам нужно использовать drain событие. HTTP-ответ является записываемым потоком. У него есть собственный внутренний буфер. Когда буфер очищается, запускается событие "слива". Вы должны узнать больше о потоках, как бы вы углубились. Это поможет вам не только в http. Вы можете найти несколько ресурсов о потоках в сети.

Другие вопросы по тегам