[PATCH] Be consistent with keepalive during graceful shutdown

Maxim Dounin mdounin at mdounin.ru
Mon Jan 21 15:17:16 UTC 2019


On Thu, Jan 17, 2019 at 11:28:54AM -0800, Yuchen Wu via nginx-devel wrote:

> # HG changeset patch
> # User Yuchen Wu <yuchen at cloudflare.com>
> # Date 1547749157 28800
> #      Thu Jan 17 10:19:17 2019 -0800
> # Node ID 8a6290c41b33c664d52d7a472400381e71ecf171
> # Parent  8acaa1161783347106dcaea574837e441e13b540
> Be consistent with keepalive during graceful shutdown
> Before, when nginx sends the Connection: Keep-Alive header and then
> nginx decides to shutdown, it will close the connection. Downstream
> may already reuse the connection for another request in the meanwhile.
> This change allows one extra use of such a connection to make sure it
> is closed cleanly.
> diff -r 8acaa1161783 -r 8a6290c41b33 src/http/ngx_http_header_filter_module.c
> --- a/src/http/ngx_http_header_filter_module.c	Thu Dec 27 19:37:34 2018 +0300
> +++ b/src/http/ngx_http_header_filter_module.c	Thu Jan 17 10:19:17 2019 -0800
> @@ -187,6 +187,10 @@
>          r->header_only = 1;
>      }
> +    if (ngx_terminate || ngx_exiting) {
> +        r->keepalive = 0;
> +    }
> +
>      if (r->headers_out.last_modified_time != -1) {
>          if (r->headers_out.status != NGX_HTTP_OK
>              && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT
> diff -r 8acaa1161783 -r 8a6290c41b33 src/http/ngx_http_request.c
> --- a/src/http/ngx_http_request.c	Thu Dec 27 19:37:34 2018 +0300
> +++ b/src/http/ngx_http_request.c	Thu Jan 17 10:19:17 2019 -0800
> @@ -2611,9 +2611,7 @@
>          r->lingering_close = 1;
>      }
> -    if (!ngx_terminate
> -         && !ngx_exiting
> -         && r->keepalive
> +    if (r->keepalive
>           && clcf->keepalive_timeout > 0)
>      {
>          ngx_http_set_keepalive(r);

Thank you for the patch.
Some notes, in no particular order:

- As per HTTP RFC, clients are expected to be prepared to 
  connection close even if there is no "Connection: close" header,

   A client, server, or proxy MAY close the transport connection at any
   time. For example, a client might have started to send a new request
   at the same time that the server has decided to close the "idle"
   connection. From the server's point of view, the connection is being
   closed while it was idle, but from the client's point of view, a
   request is in progress.

   This means that clients, servers, and proxies MUST be able to recover
   from asynchronous close events. Client software SHOULD reopen the
   transport connection and retransmit the aborted sequence of requests
   without user interaction so long as the request sequence is
   idempotent (see section 9.1.2).

  Given this, nginx more or less doesn't care when it closes idle 
  (keepalive) connections.  In particular, it does so when 
  keepalive_timeout expires (which can be quite low), on graceful 
  shutdown of worker process, and also when there isn't enough 

- Waiting for another request on graceful shutdown means that old 
  worker processes will be running for keepalive_timeout time even 
  if there are no requests in progress.  While this might not be 
  important for configurations where are requests in progress for 
  significantly longer time, this is an important change for 
  configurations where normally no in-progress requests and so 
  configuration reloads are more or less immediate now.  This should 
  be carefully considered before changing the behaviour (if at all).

- The patch suggested introduces inconsistency between handling of 
  connections which were moved to keepalive before shutdown was 
  requested, and connections which are moving to keepalive after 
  this point.

- The patch suggested introduces connections which are in idle 
  state, yet not closed after a shutdown request.  There should be 
  no such connections, and the fact that such connections are not 
  closed immediately is a result of an optimization, see 

If you want to improve keepalive connection handling on shutdown / 
configuration reload, you may want to focus on less intrusive 
changes, in particular:

- Reset r->keepalive on shutdown if it is still possible (as 
  ngx_http_header_filter_module.c part of your patch does).  

- Try to process pipelined requests if there are any if nginx 
  worker is shutting down but wasn't yet able to announce 
  "Connection: close" to the client.

Maxim Dounin

More information about the nginx-devel mailing list