[PATCH] Delayed closing of idle connections

Sunggon Song sunggon.song at quantil.com
Wed Jul 17 01:08:13 UTC 2024


# HG changeset patch
# User Sunggon Song <sunggon.song at quantil.com>
# Date 1721178360 -32400
#      Wed Jul 17 10:06:00 2024 +0900
# Node ID 3db2df01147dcbcc7bc63670207a0aa2439f6a8c
# Parent  072ca4906154effb64cbf8209dfe86742ff074d7
[PATCH] Delayed closing of idle connections

Delays processing of closing idle connection to read unread requests
while nginx performs a graceful shutdown.
This is the case where the client sent the request message
through the keepalive(idle) connection, but nginx has not yet read it
from the socket recv buffer.
If there is no delay time and there are some unread requests
in the socket recv buffer, the idle connection is immediately closed
and a TCP reset is sent to the client by the TCP stack of the kernel.

diff -r 072ca4906154 -r 3db2df01147d src/core/nginx.c
--- a/src/core/nginx.c Thu Jun 27 17:29:56 2024 +0400
+++ b/src/core/nginx.c Wed Jul 17 10:06:00 2024 +0900
@@ -153,6 +153,13 @@
       0,
       NULL },

+    { ngx_string("close_idle_connections_delay"),
+      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_close_idle_connecions_delay,
+      0,
+      offsetof(ngx_core_conf_t, close_idle_connections_delay),
+      NULL },
+
       ngx_null_command
 };

@@ -1125,6 +1132,8 @@
     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
     ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;

+    ccf->close_idle_connections_delay = NGX_CONF_UNSET;
+
     if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
         != NGX_OK)
     {
@@ -1148,6 +1157,8 @@
     ngx_conf_init_value(ccf->worker_processes, 1);
     ngx_conf_init_value(ccf->debug_points, 0);

+    ngx_conf_init_value(ccf->close_idle_connections_delay, 0);
+
 #if (NGX_HAVE_CPU_AFFINITY)

     if (!ccf->cpu_affinity_auto
diff -r 072ca4906154 -r 3db2df01147d src/core/ngx_conf_file.c
--- a/src/core/ngx_conf_file.c Thu Jun 27 17:29:56 2024 +0400
+++ b/src/core/ngx_conf_file.c Wed Jul 17 10:06:00 2024 +0900
@@ -1484,3 +1484,31 @@

     return NGX_CONF_ERROR;
 }
+
+char *
+ngx_conf_set_close_idle_connecions_delay(ngx_conf_t *cf, ngx_command_t
*cmd,
+        void *conf)
+{
+    char  *p = conf;
+
+    time_t           *sp;
+    ngx_str_t        *value;
+
+    sp = (time_t *) (p + cmd->offset);
+    if (*sp != NGX_CONF_UNSET) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    *sp = ngx_parse_time(&value[1], 1);
+
+    if (*sp == (time_t) NGX_ERROR) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                    "invalid value \"%s\"", value[i].data);
+
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
diff -r 072ca4906154 -r 3db2df01147d src/core/ngx_conf_file.h
--- a/src/core/ngx_conf_file.h Thu Jun 27 17:29:56 2024 +0400
+++ b/src/core/ngx_conf_file.h Wed Jul 17 10:06:00 2024 +0900
@@ -290,6 +290,7 @@
 char *ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void
*conf);
 char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void
*conf);
 char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void
*conf);
-
+char *ngx_conf_set_close_idle_connecions_delay(ngx_conf_t *cf,
+    ngx_command_t *cmd, void *conf);

 #endif /* _NGX_CONF_FILE_H_INCLUDED_ */
diff -r 072ca4906154 -r 3db2df01147d src/core/ngx_cycle.h
--- a/src/core/ngx_cycle.h Thu Jun 27 17:29:56 2024 +0400
+++ b/src/core/ngx_cycle.h Wed Jul 17 10:06:00 2024 +0900
@@ -118,6 +118,8 @@
     ngx_array_t               env;
     char                    **environment;

+    time_t                    close_idle_connections_delay;
+
     ngx_uint_t                transparent;  /* unsigned  transparent:1; */
 } ngx_core_conf_t;

diff -r 072ca4906154 -r 3db2df01147d src/os/unix/ngx_process_cycle.c
--- a/src/os/unix/ngx_process_cycle.c Thu Jun 27 17:29:56 2024 +0400
+++ b/src/os/unix/ngx_process_cycle.c Wed Jul 17 10:06:00 2024 +0900
@@ -51,6 +51,7 @@
 sig_atomic_t  ngx_noaccept;
 ngx_uint_t    ngx_noaccepting;
 ngx_uint_t    ngx_restart;
+ngx_uint_t    ngx_delayed_close_done;


 static u_char  master_process[] = "master process";
@@ -698,6 +699,9 @@
 static void
 ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
 {
+    time_t            now;
+    ngx_core_conf_t  *ccf;
+    time_t            delay_sec;
     ngx_int_t worker = (intptr_t) data;

     ngx_process = NGX_PROCESS_WORKER;
@@ -706,10 +710,26 @@
     ngx_worker_process_init(cycle, worker);

     ngx_setproctitle("worker process");
+    delay_sec = 0;
+    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_core_module);

     for ( ;; ) {

         if (ngx_exiting) {
+            now = ngx_time();
+            if (ccf->close_idle_connections_delay &&
+                    !ngx_delayed_close_done)
+            {
+
+                if (!delay_sec) {
+                    delay_sec = now + ccf->close_idle_connections_delay;
+                } else {
+                    if (delay_sec < now) {
+                        ngx_close_idle_connections(cycle);
+                        ngx_delayed_close_done = 1;
+                    }
+                }
+            }
             if (ngx_event_no_timers_left() == NGX_OK) {
                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
                 ngx_worker_process_exit(cycle);
@@ -735,7 +755,9 @@
                 ngx_exiting = 1;
                 ngx_set_shutdown_timer(cycle);
                 ngx_close_listening_sockets(cycle);
-                ngx_close_idle_connections(cycle);
+                if (!ccf->close_idle_connections_delay) {
+                    ngx_close_idle_connections(cycle);
+                }
                 ngx_event_process_posted(cycle, &ngx_posted_events);
             }
         }
@@ -941,6 +963,16 @@
 {
     ngx_uint_t         i;
     ngx_connection_t  *c;
+    ngx_core_conf_t   *ccf;
+
+    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_core_module);
+
+    if (ccf->close_idle_connections_delay &&
+            !ngx_delayed_close_done)
+    {
+        ngx_close_idle_connections(cycle);
+        ngx_delayed_close_done = 1;
+    }

     for (i = 0; cycle->modules[i]; i++) {
         if (cycle->modules[i]->exit_process) {
















Best Regards and thanks,
Sunggon
---------------------------------------------------------------------
Sunggon Song I Principal Research Engineer
Cache Team
Office. 82-2-3441-0375    Cell. 82-10-8744-0133
E-mail. sunggon.song at cdnetworks.co.kr, sunggon.song at quantil.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20240717/316fcbe9/attachment-0001.htm>


More information about the nginx-devel mailing list