vapor / http

🚀 Non-blocking, event-driven HTTP built on Swift NIO.
MIT License
238 stars 65 forks source link

server back-pressure support #361

Closed tanner0101 closed 4 years ago

tanner0101 commented 5 years ago

HTTPKit.HTTPServer should support back-pressure, meaning it should stop reading new data from the OS if it is unable to write data as quickly.

To accomplish this, we should first consider adding NIO's BackPressureHandler to the default server pipeline. This will stop accepting reads on a given socket if the socket is no longer writable.

However, other things besides the connected socket may need to write more slowly than is possible to read. For example, assume you are streaming body chunks from an incoming file upload and writing them to disk. If the disk writes are slower than incoming chunks, the chunks will start to fill up memory. To remedy this, HTTPRequestPartDecoder could wait for body chunks to be handled before reading more data. This would involved accounting from asynchronous handling of chunks in HTTPBody.Stream--probably with a Promise.

weissi commented 5 years ago

+100 for supporting back-pressure.

You correctly describe what NIO's BackPressureHandler does, for HTTP servers there's usually slightly more manual work needed. They might do a huge file upload and in the end only respond HTTP/1.1 200 OK, that's it. And you only write (very little) after the file has been uploaded which will probably lead to the socket being always writeable in which case BackPressureHandler does nothing :(.

You'd implement back-pressure in NIO by having a ChannelOutboundHandler that stops forwarding read() calls when the sink gets backed up. Same idea as BackPressureHandler's implementation, just a different signal to start holding off the reads.

tanner0101 commented 4 years ago

This has been added for a while now.