Quick reminder about HTTP

From a TCP point of view, HTTP protocol is stateless. This means the TCP connection may be closed after each response sent by a server. This is the Connection-Close mode. HTTP also supports sending multiple requests over a single TCP connection. This is the Keep-Alive mode.

It’s up to the client and the server to negotiate the the HTTP mode they’re going to use.

Note

The Connection-Close mode has precedence over the Keep-Alive one.

HTTP modes in HAProxy

When mode http is turned on, HAProxy processes HTTP protocol for each request and response passing through.

HAProxy supports a few keywords to define its compatibility with HTTP Connection-Close or Keep-Alive modes for the flow being processed. It may be set up in the frontend or backend section. HAProxy’s processing mode is defined by the combination of these options set up in the frontend and backend crossed by the flow being processed.

Below is a list of modes and options that support them:

KAL keep alive (option http-keep-alive) which is the default mode: all requests and responses are processed, and connections remain open but idle between response and next request
TUN tunnel (option http-tunnel): this was the default mode for ALOHA up to 5.5 included: only the first request and response are processed, and everything else is forwarded with no analysis at all. This mode should not be used as it creates lots of trouble with logging, HTTP processing, cookie insertion, X-Forwarded-For header, etc…
PCL passive close (option httpclose): exactly the same as tunnel mode, but with Connection: close HTTP header field appended in both directions to try to make both ends close after the first request/response exchange
SCL server close (option http-server-close): the server-facing connection is closed once the end of the response has been received, but the client-facing connection remains open
FCL forced close (option forceclose): the connection is actively closed after the end of the response

The effective mode that will be applied to a connection passing through a frontend and a backend is determined by both proxy modes according to the following matrix. In short, the modes are symmetric, keep-alive is the weakest option and forceclose is the strongest:

Frontend Backend KAL TUN PCL SCL FCL
KAL KAL TUN PCL SCL FCL
TUN TUN TUN PCL SCL FCL
PCL PCL PCL PCL FCL FCL
SCL SCL SCL FCL SCL FCL
FCL FCL FCL FCL FCL FCL

Keep Alive (KAL) mode

This is the default mode, set when no other options are setup.

In this mode, HAProxy tries to keep connections opened on both the client and the server side. Each client has its dedicated server side connection and both remains opened after the last response, until the next query or a timeout occurs.

KAL has the lowest latency on both the client and the server and in case of high request rate, it will be the fastest one.

It is mandatory when NTLM authentication is an application requirement.

This mode is recommended when load-balancing static or cache servers or application server if the application doesn’t suffer from a too high number of established connections.

To enable it, both the frontend and the backend must be set to option http-keep-alive.

The connection on the server side may be closed in two cases:

  • Content switching: the current request has been forwarded to another backend, hence a different server
  • Load-balancing algorithm elected a new server in the backend

To avoid the second case, it is possible to set the option option prefer-last-server in the backend section.

Note

Avoid using option prefer-last-server with URL hash algorithm when load-balancing cache servers, since you’ll make your content mixed up in all the caches, loosing the benefit of the hash.

When set up in the defaults section, you can use no option http-keep-alive to disable it locally in a frontend or backend.

The Tunnel (TUN) mode

In this mode, HAProxy analyzes the first request and the first response of each incoming connection, then it estblishes a tunnel between the client and the server and let them talk together without furhter analyzis of HTTP protocol.

By design, this mode has impact over the following features, which apply to the first request and response in the session only:

  • No logs generated
  • HTTP header parsing
  • HTTP header manipulation
  • Cookie processing
  • Content switching
  • Insertion of X-Forwarded-For header

To enable it, either the frontend or the backend must be set to option http-tunnel and none of the following modes below should be set:

When setup in the defaults section, you can use no option http-tunnel to disable it locally in a frontend or backend.

Note

This used to be the default mode until ALOHA 5.5. Since 6.0, HAProxy uses keep-alive mode.

Passive Close (PCL) mode

In this mode, HAProxy works in HTTP tunnel mode and set or force the HTTP Connection: close header in both client and server directions. If not set, it adds it. Each peer of each connection (client or server side) should close the connection on their own.

It might happen that some servers or clients ignores the Connection: close header and keep the connection alive. To force the close of the connection, HAProxy can actively do it using the force-close mode.

To enable it, either the frontend or the backend must be set to option httpclose and none of the following option below should be set:

When setup in the defaults section, you can use no option httpclose to disable it locally in a frontend or backend.

Server Close (SCL) mode

In this mode, HAProxy works in keep-alive mode on the client side and in connection-close mode on the server side.

It provides the latency on the client side (slow network) and the fastest session reuse on the server side to save server resources. It also permits non-keepalive capable servers to be served in keep-alive from a client perspective.

Note

Some servers may work incorrectly when the Connection: close header is set in the request. They automatically refrain from using the chunked encoding for responses of unknown length, while this is totally unrelated.

The immediate effect is that this prevents HAProxy from maintaining the client connection alive. A second effect is that a client or a cache could receive an incomplete response without being aware of it, and consider the response complete.

Turn on the option option http-pretend-keepalive when this happens.

To enable it, either the frontend or the backend must be set to option http-server-close and none of the following option below should be set:

When setup in the defaults section, you can use no option http-server-close to disable it locally in a frontend or backend.

Force Close (FCL) mode

In this mode, HAProxy actively closes the TCP connection on the server side as soon as it has received the whole response.

Note

Some servers may work incorrectly when the Connection: close header is set in the request. They automatically refrain from using the chunked encoding for responses of unknown length, while this is totally unrelated.

The immediate effect is that this prevents HAProxy from maintaining the client connection alive. A second effect is that a client or a cache could receive an incomplete response without being aware of it, and consider the response complete.

Turn on the option option http-pretend-keepalive when this happens.

To enable it, either the frontend or the backend must be set to option forceclose.

When setup in the defaults section, you can use no option forceclose to disable it locally in a frontend or backend.

Configuration examples

Run server-close mode for all the frontend(s)/backend(s) in the configuration:

defaults
  option http-server-close

Turn on Keep-alive mode on whole configuration but backend b_myapp where we want server-close mode:

defaults
  option http-keep-alive

...
backend b_myapp
  option http-server-close

Configure for compatibility with an NTLM application:

defaults
  option http-server-close

...

frontend f_myapp_ntlm
  bind 10.0.0.1:80
  option http-keep-alive
  default_backend b_myapp_ntlm

backend b_myapp_ntlm
  option http-keep-alive
  server s1 10.0.0.11:80 check

Set compatible mode with certain older Tomcat servers that improperly handle server-close mode:

backend b_myapp
  option http-server-close
  option http-pretend-keepalive