[PATCH] Introduced worker_shutdown_idle_delay

Roman Arutyunyan arut at nginx.com
Fri Jan 26 07:03:31 UTC 2024


Hi Artem,

On Wed, Nov 08, 2023 at 07:51:39AM +0300, Artem Pogartsev via nginx-devel wrote:
> # HG changeset patch
> # User Artem Pogartsev <iam at arteomp.com>
> # Date 1699416491 -10800
> #      Wed Nov 08 07:08:11 2023 +0300
> # Node ID eb0dd3d903431f4dd7a62d629db457ecddeadd96
> # Parent  7ec761f0365f418511e30b82e9adf80bc56681df
> Introduced worker_shutdown_idle_delay.
> 
> The directive configures a delay before closing idle connections to be used
> when gracefully shutting down worker processes. When the timer expires, nginx
> will attempt to close any remaining idle connections.
> 
> The delay is only added for connections with the "shutdown_delay" flag, and
> currently it's only keepalive HTTP/1.1 connections. The behavior is not changed
> for protocols that have built-in graceful shutdown mechanisms, such as GOAWAY
> frames in HTTP2 and HTTP3.
> 
> Although it's perfectly fine to close an HTTP/1.1 connection at any time
> according to RFC 9112, it may still be useful to delay closing a connection,
> wait for the next client request, and close the connection with a
> "Connection: close" header to avoid unnecessary retries by clients. This is
> especially important for environments with frequent nginx reloads and large
> amounts of non-idempotent requests which are quite problematic for automatic
> retries.
> 
> Should be used carefully to not delay configuration reloads too much (and thus
> increase nginx resource usage), and ideally in combination with properly
> configured clients:

[..]

I suggest a simpler patch which disables idle mode for HTTP keepalive
connections.  Such connections will not be closed until one of the timeouts
(keepalive_timeout or worker_shutdown_timeout) expires or when a new request
arrives and receives 'Connection: close'.

--
Roman Arutyunyan
-------------- next part --------------
# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1706205992 -14400
#      Thu Jan 25 22:06:32 2024 +0400
# Node ID 165096c37f91640042e93f115b7281a3c690bc9d
# Parent  d9bc503a4c39d29480e640347e0b992d83c792bc
Added "keepalive_worker_shutdown" directive.

The directive allows disabling idle mode for HTTP keepalive connections.
Such a connection will not be closed on worker shutdown until a new request is
received on that connection or one of keepalive_timeout/worker_shutdown_timeout
expires.

By default idle mode is enabled, as before.

diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -523,6 +523,13 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, keepalive_disable),
       &ngx_http_core_keepalive_disable },
 
+    { ngx_string("keepalive_worker_shutdown"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, keepalive_shutdown),
+      NULL },
+
     { ngx_string("satisfy"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_enum_slot,
@@ -3607,6 +3614,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
     clcf->keepalive_header = NGX_CONF_UNSET;
     clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
+    clcf->keepalive_shutdown = NGX_CONF_UNSET;
     clcf->lingering_close = NGX_CONF_UNSET_UINT;
     clcf->lingering_time = NGX_CONF_UNSET_MSEC;
     clcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
@@ -3897,6 +3905,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     ngx_conf_merge_value(conf->chunked_transfer_encoding,
                               prev->chunked_transfer_encoding, 1);
     ngx_conf_merge_value(conf->etag, prev->etag, 1);
+    ngx_conf_merge_value(conf->keepalive_shutdown, prev->keepalive_shutdown, 1);
 
     ngx_conf_merge_uint_value(conf->server_tokens, prev->server_tokens,
                               NGX_HTTP_SERVER_TOKENS_ON);
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -407,6 +407,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_uint_t    server_tokens;           /* server_tokens */
     ngx_flag_t    chunked_transfer_encoding; /* chunked_transfer_encoding */
     ngx_flag_t    etag;                    /* etag */
+    ngx_flag_t    keepalive_shutdown;      /* keepalive_worker_shutdown */
 
 #if (NGX_HTTP_GZIP)
     ngx_flag_t    gzip_vary;               /* gzip_vary */
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -3302,7 +3302,10 @@ ngx_http_set_keepalive(ngx_http_request_
     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
 #endif
 
-    c->idle = 1;
+    if (clcf->keepalive_shutdown) {
+        c->idle = 1;
+    }
+
     ngx_reusable_connection(c, 1);
 
     ngx_add_timer(rev, clcf->keepalive_timeout);


More information about the nginx-devel mailing list