As I understand it, one of the consequences of Node's evented IO model is the inability to tell a Node process that is (for example) receiving data over a TCP socket, to block, once you've hooked up your receiving event handlers (or otherwise started listening for data).
If the receiver can't process the incoming data fast enough, "unbounded concurrency" can result, whereby node under-the-hood continues to read data off the socket as fast as it can, scheduling new data events on the event loop instead of block on the socket, until the process eventually runs out of memory and dies.
The receiver can't tell node to slow its reading, which would otherwise allow TCP's inbuilt flow control mechanisms to kick in and indicate to the sender that it needs to slow down.
Firstly, is what I've described so far accurate? Is there something I've missed that allows node to avoid this situation?
One of the much touted features of Node Streams is the automatic handling of backpressure.
AFAIK, the only way a writable stream (of a tcp socket) can tell if it needs to slow down or not is by looking at socket.bufferSize
(indicating the amount of data written to the socket but not yet sent). Given that Node at the receiving end always reads as fast as it can, this can only indicate a slow network connection between sender and receiver, and NOT whether the receiver can't keep up.
So secondly, can Node Streams automatic backpressure somehow work in this situation to deal with a receiver that can't keep up?
It also seems that this problem affects browsers receiving data via websockets, for the similar reason that the websockets API doesn't provide a mechanism to tell the browser to slow its reading from the socket.
Is the only solution to this problem for Node (and browsers using websockets) to implement a manual flow control mechanism at the application level, to explicitly tell the sending process to slow down?
highWaterMark
option. This is how the backpressure is handled: node will slow its reading when it fills its incoming buffer; and will also stop sending data if the outgoing buffer is full. Node reads as fast as it can… until it fills up its buffer. It won't read any more data until the buffer is empty again. I'd suggest studying the Stream Buffer Length of this example. – Costanzo