[PATCH 0 of 1] Upstream: add propagate_connection_close directive

Shawn J. Goff shawgoff at amazon.com
Tue Jan 6 01:47:28 UTC 2015

On 01/04/2015 07:47 PM, Maxim Dounin wrote:
> Hello!

Hi, thanks for taking the time to review the patch!

> On Fri, Jan 02, 2015 at 04:03:58PM -0800, Shawn J. Goff wrote:
>> This patch adds a new directive to the upstream module:
>> propagate_connection_close. It puts a "Connection: close" header in
>> the downstream response if the upstream server sent one. This is
>> useful when Nginx is used as HTTP/HTTPS endpoints with load blancers
>> in front of them. It allows the upstream server to close connections
>> in order to shed load.
> You may try to better elaborate on the problem you are trying to
> solve and why existing mechanisms do not work for you.

We have HTTP servers that sit behind TCP load balancers. The servers 
currently have a protocol for making sure long-lived connections are 
balanced among them. This involves closing specific connections at 
appropriate times; this causes the client to open a new connection, 
which will most-likely be handled by another host. We now want those 
hosts to accept HTTPS connections in a well-understood, reliable way 
that has acceptable performance characteristics. We are hoping to use 
Nginx. We found that it breaks our load-balancing because connections 
are not being closed.

> As of now, nginx can:
> but
> - Disable keepalive completely ("keepalive_timeout 0") on a
>    per-location basis (http://nginx.org/r/keepalive_timeout).

This will turn off keep-live for every connection at the location, which 
is not what we want - we want to close specific existing connections.

> - Disable keepalive based on a number of requests served in a
>    connection (http://nginx.org/r/keepalive_requests).

This is not enough; we already have a way of choosing connections to 
close, and it's not only based on the number of requests (or on length 
of idle time, keepalive_timeout).

> - Disable keepalive in some specific conditions
>    (http://nginx.org/r/keepalive_disable).

This disables keep-alive per browser, which is very much a different 
thing, and not our problem.

> - Disable chunked transfer encoding on a per-location basis
>    (http://nginx.org/r/chunked_transfer_encoding).

This is also not going to help us.

> I think this addresses most, if not all, problems in the links you
> provided.  In particular, low enough keepalive_requests can be
> used to distribute load if needed.

It can, at the expense of higher latency. We are extremely 
latency-sensitive, so we've put a lot of work into ensuring our p99.9+ 
latencies are consistent and as low as possible. To that end, we have 
our own method of distributing the load that should really not be part 
of Nginx, as it's highly specific to our service.

>> I can submit a documentation patch if this patch is accepted.
> The approach taken in the patch looks wrong, for multiple reasons,
> in particular:
> - The upstream module isn't expected to contain it's own
>    directives, expect ones used to define upstream{} blocks.
>    Instead, there should be directives in modules implementing
>    protocols, like "proxy_foo_bar...".

I had considered putting it in upstream, but thought the having it in 
location{} would give more flexibility. I'd be fine putting it in 
upstream{} instead.

As far as putting it in a proxy_foo_bar module, I took a look through 
the modules here: 
http://nginx.org/en/docs/http/ngx_http_proxy_module.html . The only one 
I see that might be appropriate is proxy_pass; are there any others you 
were referring to?

I chose to put this in the upstream module because that is what strips 
out the Connection header and sets the connection_close field in the 
headers_in struct that is specific to the upstream module.

> - The "Connection: close" header is a hop-by-hop http header, and
>    "propogating" it looks like a bad idea.  It mixes control of the
>    nginx-to-backend connection with control of the client-to-nginx
>    connection.  Instead, there should be a way to control these
>    connections separately.  It may be an option to add X-Accel-...
>    header instead, similart to X-Accel-Limit-Rate.  Though this
>    approach has it's own problems too, see below.

It is hop-by-hop, but we're not really wanting Nginx as a separate hop; 
that is just a byproduct. Nginx on the same host as the upstream server; 
it's just there to take care of TLS for us.

> - It is not possible to control connections that aren't proxied
>    to backends but are handled locally - e.g., when using embedded
>    perl or even just serving static files.
> If there is a need to allow dynamic control of keepalive, I think
> that proper way would be to extend the "keepalive_disable"
> directive with variables support.

How would this work? Should I set a variable depending on whether some 
X-Accel- header is present, then set keepalive_disable per request 
depending on that variable?

More information about the nginx-devel mailing list