node.js - nodejs http response.write : is it possible out-of-memory?

标签 node.js http out-of-memory response multipart-mixed-replace

如果我有以下代码每 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的源码,得到了结论:
它确实会导致“内存不足”错误。我应该检查 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. 如果通过 http 发送,这不是一个好主意。如果在指定时间内未完成请求,浏览器可能会认为该请求超时。服务器也将关闭空闲时间过长的连接。如果客户端跟不上,超时几乎是肯定的。

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

  3. 假设您有机会使数据响应过载,然后在某个时候服务器将结束连接并响应 413 Request Entity Too Large,具体取决于设置的限制。

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

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

更新

您需要使用 drain事件。 http 响应是一个可写流。它有自己的内部缓冲区。当缓冲区清空时,将触发 drain 事件。随着您深入研究,您应该更多地了解流。这不仅会在 http 中帮助您。您可以在 Web 上找到有关流的多种资源。

关于node.js - nodejs http response.write : is it possible out-of-memory?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24901936/

相关文章:

javascript - 尚未为模型注册架构

node.js - 使用 WebSockets 过滤和排序结果?

java - 使用 Java 通过 HTTP 下载未知长度的文件

android - 每次都创建新的 picasso 实例可以吗

scala - SBT 子项目内存不足

node.js - 在浏览器上下载文件

http - 在服务器端的 Dart 中,如何在 HttpClient 中设置 header

http - 将 BASIC 身份验证与客户端证书身份验证结合使用

jakarta-ee - Java EE 对象监控工具

regex - 多个express的路由器使用根路径