]> git.kaiwu.me - nginx.git/commitdiff
Core: idle connections now closed only once on exiting.
authorValentin Bartenev <vbart@nginx.com>
Tue, 11 Aug 2015 13:28:55 +0000 (16:28 +0300)
committerValentin Bartenev <vbart@nginx.com>
Tue, 11 Aug 2015 13:28:55 +0000 (16:28 +0300)
Iterating through all connections takes a lot of CPU time, especially
with large number of worker connections configured.  As a result
nginx processes used to consume CPU time during graceful shutdown.
To mitigate this we now only do a full scan for idle connections when
shutdown signal is received.

Transitions of connections to idle ones are now expected to be
avoided if the ngx_exiting flag is set.  The upstream keepalive module
was modified to follow this.

src/core/ngx_connection.c
src/core/ngx_connection.h
src/http/modules/ngx_http_upstream_keepalive_module.c
src/os/unix/ngx_process_cycle.c
src/os/win32/ngx_process_cycle.c

index 00c5a08e6b2085630964f4b276bfcd579e6a157a..9f2675b886d3e03a64e90f9379ba5cf09fb223c3 100644 (file)
@@ -1163,6 +1163,26 @@ ngx_drain_connections(void)
 }
 
 
+void
+ngx_close_idle_connections(ngx_cycle_t *cycle)
+{
+    ngx_uint_t         i;
+    ngx_connection_t  *c;
+
+    c = cycle->connections;
+
+    for (i = 0; i < cycle->connection_n; i++) {
+
+        /* THREAD: lock */
+
+        if (c[i].fd != -1 && c[i].idle) {
+            c[i].close = 1;
+            c[i].read->handler(c[i].read);
+        }
+    }
+}
+
+
 ngx_int_t
 ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
     ngx_uint_t port)
index a49aa9579ed2e39ada820fd76a20015c75d97c1b..c3aca7f47d87fcb1576e5affe290bcb2ffbf3451 100644 (file)
@@ -215,6 +215,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle);
 void ngx_configure_listening_sockets(ngx_cycle_t *cycle);
 void ngx_close_listening_sockets(ngx_cycle_t *cycle);
 void ngx_close_connection(ngx_connection_t *c);
+void ngx_close_idle_connections(ngx_cycle_t *cycle);
 ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
     ngx_uint_t port);
 ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text);
index 768881ee41accd646ee6831ac4c973ba470759ac..51887b4e870007cca353b74940f79ce60307a341 100644 (file)
@@ -302,6 +302,10 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
         goto invalid;
     }
 
+    if (ngx_terminate || ngx_exiting) {
+        goto invalid;
+    }
+
     if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
         goto invalid;
     }
index c69932ecd6ede8826cd3c9234526dd4162658246..5da09116fc74c586788522e8178cda0d2a1523f0 100644 (file)
@@ -728,9 +728,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
 {
     ngx_int_t worker = (intptr_t) data;
 
-    ngx_uint_t         i;
-    ngx_connection_t  *c;
-
     ngx_process = NGX_PROCESS_WORKER;
     ngx_worker = worker;
 
@@ -741,19 +738,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
     for ( ;; ) {
 
         if (ngx_exiting) {
-
-            c = cycle->connections;
-
-            for (i = 0; i < cycle->connection_n; i++) {
-
-                /* THREAD: lock */
-
-                if (c[i].fd != -1 && c[i].idle) {
-                    c[i].close = 1;
-                    c[i].read->handler(c[i].read);
-                }
-            }
-
             ngx_event_cancel_timers();
 
             if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
@@ -781,8 +765,9 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
             ngx_setproctitle("worker process is shutting down");
 
             if (!ngx_exiting) {
-                ngx_close_listening_sockets(cycle);
                 ngx_exiting = 1;
+                ngx_close_listening_sockets(cycle);
+                ngx_close_idle_connections(cycle);
             }
         }
 
index 203bece3f5de9498bc189c96388d5ffb149733ae..06ff8b50eee0b901451e02ace6a8aa35d8efaed9 100644 (file)
@@ -761,10 +761,8 @@ failed:
 static ngx_thread_value_t __stdcall
 ngx_worker_thread(void *data)
 {
-    ngx_int_t          n;
-    ngx_uint_t         i;
-    ngx_cycle_t       *cycle;
-    ngx_connection_t  *c;
+    ngx_int_t     n;
+    ngx_cycle_t  *cycle;
 
     cycle = (ngx_cycle_t *) ngx_cycle;
 
@@ -780,19 +778,6 @@ ngx_worker_thread(void *data)
     while (!ngx_quit) {
 
         if (ngx_exiting) {
-
-            c = cycle->connections;
-
-            for (i = 0; i < cycle->connection_n; i++) {
-
-                /* THREAD: lock */
-
-                if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
-                    c[i].close = 1;
-                    c[i].read->handler(c[i].read);
-                }
-            }
-
             ngx_event_cancel_timers();
 
             if (ngx_event_timer_rbtree.root
@@ -814,8 +799,9 @@ ngx_worker_thread(void *data)
             ngx_quit = 0;
 
             if (!ngx_exiting) {
-                ngx_close_listening_sockets(cycle);
                 ngx_exiting = 1;
+                ngx_close_listening_sockets(cycle);
+                ngx_close_idle_connections(cycle);
             }
         }