mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-10-26 22:20:59 +01:00
MINOR: proxy: explicitly permit abortonclose on frontends and clarify the doc
The "abortonclose" option was recently deprecated in frontends because its action was essentially limited to the backend part (queuing etc). But in 3.3 we started to support it for TLS on frontends, though it would only work when placed in a defaults section. Let's officially support it in frontends, and take this opportunity to clarify the documentation on this topic, which was incomplete regarding frontend and TLS support. Now the doc tries to better cover the different use cases.
This commit is contained in:
parent
f657ffc6e7
commit
c42e62d890
@ -5571,7 +5571,7 @@ maxconn X X X -
|
||||
mode X X X X
|
||||
monitor fail - X X -
|
||||
monitor-uri X X X -
|
||||
option abortonclose (*) X - X X
|
||||
option abortonclose (*) X X X X
|
||||
option allbackups (*) X - X X
|
||||
option checkcache (*) X - X X
|
||||
option clitcpka (*) X X X -
|
||||
@ -9044,46 +9044,56 @@ monitor-uri <uri>
|
||||
|
||||
option abortonclose
|
||||
no option abortonclose
|
||||
Enable or disable early dropping of aborted requests pending in queues.
|
||||
Enable or disable early abortion of not started processing when client closes
|
||||
|
||||
May be used in the following contexts: tcp, http
|
||||
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
yes | no | yes | yes
|
||||
yes | yes | yes | yes
|
||||
|
||||
Arguments : none
|
||||
|
||||
In presence of very high loads, the servers will take some time to respond.
|
||||
The per-instance connection queue will inflate, and the response time will
|
||||
increase respective to the size of the queue times the average per-stream
|
||||
response time. When clients will wait for more than a few seconds, they will
|
||||
often hit the "STOP" button on their browser, leaving a useless request in
|
||||
the queue, and slowing down other users, and the servers as well, because the
|
||||
request will eventually be served, then aborted at the first error
|
||||
encountered while delivering the response.
|
||||
TCP connections support being closed independently in each direction, and a
|
||||
connection with only one direction closed is often said to be "half-closed".
|
||||
Originally when the HTTP ecosystem was mostly made of the "close mode", with
|
||||
only one request and one response per connection before closing, it was
|
||||
pretty frequent to see scripted clients send their request, close the sending
|
||||
side, wait for the response, receive the close indication and be done with
|
||||
this. But with the arrival of keep-alive and more advanced protocols, this
|
||||
practice has practically disappeared and the only cases where a client closes
|
||||
before receiving its response is essentially when the user wants to abort a
|
||||
transfer, or when a timeout strikes and the connection is closed.
|
||||
|
||||
As there is no way to distinguish between a full STOP and a simple output
|
||||
close on the client side, HTTP agents should be conservative and consider
|
||||
that the client might only have closed its output channel while waiting for
|
||||
the response. However, this introduces risks of congestion when lots of users
|
||||
do the same, and is completely useless nowadays because probably no client at
|
||||
all will close the stream while waiting for the response. Some HTTP agents
|
||||
support this behavior (Squid, Apache, HAProxy), and others do not (TUX, most
|
||||
hardware-based load balancers). So the probability for a closed input channel
|
||||
to represent a user hitting the "STOP" button is close to 100%, and the risk
|
||||
of being the single component to break rare but valid traffic is extremely
|
||||
low, which adds to the temptation to be able to abort a stream early while
|
||||
still not served and not pollute the servers.
|
||||
These two situations (half-closed vs abort) are undistinguishable from the
|
||||
server side (here the HAProxy listener). This is a problem because leaving
|
||||
the connection alive and continuing to process a request when clients abort
|
||||
can cost a lot of resources, particularly if the closure is the result of a
|
||||
user hitting the "reload" button, as it means new requests are queued without
|
||||
the previous ones being aborted. And conversely, systematically aborting when
|
||||
facing such a half-close situation would break a number of TCP applications
|
||||
and even some HTTP ones on internal networks interacting with legacy agents.
|
||||
|
||||
In HAProxy, the user can choose the desired behavior using the option
|
||||
"abortonclose". By default (without the option) the behavior is HTTP
|
||||
compliant and aborted requests will be served. But when the option is
|
||||
specified, a stream with an incoming channel closed will be aborted while
|
||||
it is still possible, either pending in the queue for a connection slot, or
|
||||
during the connection establishment if the server has not yet acknowledged
|
||||
the connection request. This considerably reduces the queue size and the load
|
||||
on saturated servers when users are tempted to click on STOP, which in turn
|
||||
reduces the response time for other users.
|
||||
The "abortonclose" option permits to choose the desired behavior:
|
||||
- when present in a frontend, it will avoid processing TLS handshakes which
|
||||
are pending on a half-closed connection. This can be the result of a user
|
||||
hitting "reload" during an HTTPS request under high load such as a VRRP
|
||||
fail-over between an active HAProxy node and the backup one: all clients
|
||||
reconnect at the same time to the new node, and all have to perform a
|
||||
costly, full TLS handshake. If it takes more than a few seconds, it's
|
||||
likely that some users will give up, and it's pointless to waste CPU
|
||||
cycles on their handshakes. Given the CPU cost of TLS handshakes, it is
|
||||
recommended to leave this option enabled on internet-facing frontends.
|
||||
|
||||
- when present in a backend, it will cause half-closed connections to try
|
||||
to abort a request that was not yet sent to a server (i.e. when it's
|
||||
pending in the queue or when trying to connect). If the request is
|
||||
already being served by a server, then the connection to the server is
|
||||
in turn switched to half-close to indicate the same condition to the
|
||||
server, which will then decide how to proceed.
|
||||
|
||||
The recommendation is to enable this option on internet-facing TLS endpoints
|
||||
and HTTP services, and to disable it for pure TCP ones as well as unexposed
|
||||
legacy environments.
|
||||
|
||||
If this option has been enabled in a "defaults" section, it can be disabled
|
||||
in a specific instance by prepending the "no" keyword before it.
|
||||
|
||||
@ -82,7 +82,7 @@ struct show_srv_ctx {
|
||||
/* proxy->options */
|
||||
const struct cfg_opt cfg_opts[] =
|
||||
{
|
||||
{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
|
||||
{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE|PR_CAP_FE, 0, 0 },
|
||||
{ "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
|
||||
{ "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
|
||||
{ "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user