mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-27 16:51:30 +02:00
Glenn Strauss from Lighttpd reported a corner case affecting curl+lighttpd that causes some uploads to degenerate to extremely suboptimal conditions under certain circumstances, and noted that many other implementations were possibly not safe against this degradation. Glenn's detailed analysis is available here: https://github.com/nghttp2/nghttp2/issues/1722 In short, curl uses a 65536 bytes buffer and the default stream window is 65535, with 16384 bytes per frame. Curl will then send 3 frames of 16384 bytes followed by one of 16383, will wait for a window update to send the last byte before recycling the buffer to read the next 64kB. On each round like this, one extra single-byte frame will be sent, and if ACKs for these single-byte frames are not aggregated, this will only allow the client to send one extra byte at a time. At some point it is possible (at least Glenn observed it) to have mostly 1-byte frames in the transfer, resulting in huge CPU usage and a long transfer. It was not possible to reproduce this with haproxy, even when playing with frame sizes, buffer sizes nor window sizes. One reason seems to be that we're using the same buffer size for the connection and the stream and that the frame headers prevent the filling of the window from happening on the same boundaries as on the sender. However it does occasionally happen to see up to two 1-byte data frames in a row, indicating that there's definitely room for improvement. The WINDOW_UPDATE frames for the connection are sent at the end of the demuxing, but the ones for the streams are currently sent immediately after a DATA frame is processed, mostly for convenience. But we don't need to proceed like this, we already have the counter of unacked bytes in rcvd_s, so we can simply use that to decide when to send an ACK. It must just be done before processing a new frame. The benefit is that contiguous frames for the same stream will now only produce a single WU, like for the connection. On complicated tests involving a client that was limited to 100 Mbps transfers and a dummy Lua-based payload consumer, it was possible to see the number of stream WU frames being halved for a 100 MB transfer, which is already a nice saving anyway. Glenn proposed a better workaround consisting in increasing the default window size to 65536. This will be done in a separate patch so that both can be studied independently in field and backported as needed. This patch is not much complicated and shold be backportable. It just needs to be tested in development first.
The HAProxy documentation has been split into a number of different files for ease of use. Please refer to the following files depending on what you're looking for : - INSTALL for instructions on how to build and install HAProxy - BRANCHES to understand the project's life cycle and what version to use - LICENSE for the project's license - CONTRIBUTING for the process to follow to submit contributions The more detailed documentation is located into the doc/ directory : - doc/intro.txt for a quick introduction on HAProxy - doc/configuration.txt for the configuration's reference manual - doc/lua.txt for the Lua's reference manual - doc/SPOE.txt for how to use the SPOE engine - doc/network-namespaces.txt for how to use network namespaces under Linux - doc/management.txt for the management guide - doc/regression-testing.txt for how to use the regression testing suite - doc/peers.txt for the peers protocol reference - doc/coding-style.txt for how to adopt HAProxy's coding style - doc/internals for developer-specific documentation (not all up to date)
Description
Languages
C
98.1%
Shell
0.8%
Makefile
0.5%
Lua
0.2%
Python
0.2%