1

如果我有以下代码每 10 毫秒重复向客户端发送数据:

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

如果客户端接收数据很慢会发生什么?

服务器会出现内存不足错误吗?

编辑:实际上连接保持活动状态,服务器无休止地发送jpeg数据(HTTP multipart/x-mixed-replace header + body + header + body.....)
因为node.js response.write是异步的,
所以有些用户猜测它可能会将数据存储在内部缓冲区中并等待低层告诉它可以发送,
所以内部缓冲区会增长,对吗?

如果我是对的,那么如何解决这个问题?
问题是 node.js 在为单个写入调用发送数据时不会通知我。

换句话说,我不能告诉用户这种方式理论上没有“内存不足”的风险以及如何解决它。


更新: 通过user568109给出的关键字“drain”事件,我研究了node.js的来源,得出结论:
确实会导致“out-of-memory”错误。我应该检查 response.write(...)===false 的返回值,然后处理响应的“drain”事件。

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;
  }
};
4

1 回答 1

2

一些陷阱:

  1. 如果通过 http 发送这不是一个好主意。如果在指定的时间内没有完成,浏览器可能会将请求视为超时。服务器也将关闭空闲时间过长的连接。如果客户端跟不上,超时几乎是肯定的。

  2. setInterval for 10ms 也受到一些限制。这并不意味着它会在每 10 毫秒后重复一次,10 毫秒是它在重复之前等待的最小值。它会比您设置的时间间隔慢。

  3. 假设您有机会用数据重载响应,然后在某些时候服务器将结束连接并413 Request Entity Too Large根据设置的限制做出响应。

  4. Node.js 具有单线程架构,最大内存限制约为 1.7 GB。如果您上述服务器限制设置得太高并且有很多传入连接,您将收到process out of memory错误消息。

因此,如果有适当的限制,它要么会超时,要么会请求太大。(并且您的程序中没有其他错误。)

更新

您需要使用drain事件。http 响应是一个可写流。它有自己的内部缓冲区。当缓冲区被清空时,就会触发排水事件。你应该了解更多关于流的知识,因为你会更深入。这不仅会在 http 中为您提供帮助。您可以在网络上找到一些关于流的资源。

于 2014-07-23T09:31:53.123 回答