简体   繁体   English

nodejs http response.write:是否可能内存不足?

[英]nodejs http response.write: is it possible out-of-memory?

If i have following code to send data repeatedly to client every 10ms: 如果我有以下代码每隔10ms反复向客户端发送数据:

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

What would happen if the client is very slow to receive the data? 如果客户端接收数据的速度非常慢,会发生什么?

Will server get out-of-memory error? 服务器会出现内存不足错误吗?

Edit: actually the connection is kept alive, sever send jpeg data endlessly (HTTP multipart/x-mixed-replace header + body + header + body.....) 编辑:实际上连接保持活动状态,服务器不断发送jpeg数据(HTTP multipart / x-mixed-replace标头+正文+标头+正文.....)
Because node.js response.write is asynchronous, 由于node.js response.write是异步的,
so some users guess it may store data in internal buffer and wait until low layer tells it can send, 因此,一些用户猜测它可能会将数据存储在内部缓冲区中,然后等到低层告知它可以发送,
so the internal buffer will grow, am i right? 这样内部缓冲区会增加,对吗?

If i am right, then how to resolve this? 如果我是对的,那么如何解决呢?
the problem is node.js does not notify me when data is send for a single write call. 问题是在为单个写调用发送数据时,node.js不会通知我。

In other word, i can not tell user this way is theoretically no risk of "out of memory" and how to fix it. 换句话说,我不能告诉用户这种方式在理论上没有“内存不足”以及如何解决的风险。


Update: By the keyword "drain" event given by user568109, i studied the source of node.js, and got conclusion: 更新:通过user568109给出的关键字“ drain”事件,我研究了node.js的来源,并得出了结论:
it really will cause "out-of-memory" error. 它确实会导致“内存不足”错误。 I should check return value of response.write(...)===false and then handle "drain" event of the response. 我应该检查response.write(...)=== false的返回值,然后处理响应的“排水”事件。

http.js: 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;
  }
};

Some gotchas: 一些陷阱:

  1. If sending over http it is not be a good idea. 如果通过http发送,则不是一个好主意。 The browser may consider the request as timeout if it is not finished within specified amount of time. 如果请求未在指定的时间内完成,则浏览器可能会将其视为超时。 Server too will close connection which is idle for too long. 服务器也将关闭空闲时间过长的连接。 If client cannot keep up, the timeout is almost certain. 如果客户端无法跟上,超时几乎可以确定。

  2. setInterval for 10ms is also subject to some restrictions. setInterval 10ms也受到一些限制。 It doesn't mean it will repeat after every 10ms, 10ms is the minimum it will wait before repeating. 这并不意味着它将每10毫秒重复一次,而10毫秒是重复之前等待的最短时间。 It will be slower than what you set the interval. 这将比您设置的间隔慢。

  3. Let's say you chance to overload the response with data, then at some point the server will end connection and respond by 413 Request Entity Too Large depending on what the limit is set. 假设您有机会使数据超载响应,然后服务器将终止连接,并根据设置的限制由413 Request Entity Too Large响应。

  4. Node.js has single threaded architecture with a max memory limitation of around 1.7 GB. Node.js具有单线程体系结构,最大内存限制约为1.7 GB。 If you set your above server limits to too high and have many incoming connections you will get process out of memory error. 如果您服务器的上述限制设置得太高,并且有许多传入连接,则将导致process out of memory不足错误。

So with appropriate limits it will either give timeout or be request too large. 因此,如果有适当的限制,它将导致超时或请求太大。 (And there are no other errors in your program.) (并且程序中没有其他错误。)

Update 更新

You need to use drain event. 您需要使用drain事件。 The http response is a writable stream. http响应是可写流。 It has its own internal buffer. 它具有自己的内部缓冲区。 When the buffer is emptied the drain event is triggered. 清空缓冲区后,将触发耗尽事件。 You should learn more about streams as you would go in deeper. 您应该更深入地了解有关流的更多信息。 This will help you not just in http. 这将不仅在http中提供帮助。 You can find several resources about streams on web. 您可以找到有关Web流的一些资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM