]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: Add way to disable active connection closing during soft-stop
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Tue, 26 Apr 2022 13:17:18 +0000 (15:17 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 26 Apr 2022 17:56:47 +0000 (19:56 +0200)
If the "close-spread-time" option is set to "infinite", active
connection closing during a soft-stop can be disabled. The 'connection:
close' header or the GOAWAY frame will not be added anymore to the
server's response and active connections will only be closed once the
clients disconnect. Idle connections will not be closed all at once when
the soft-stop starts anymore, and each idle connection will follow its
own timeout based on the multiple timeouts set in the configuration (as
is the case during regular execution).

This feature request was described in GitHub issue #1614.
This patch should be backported to 2.5. It depends on 'MEDIUM: global:
Add a "close-spread-time" option to spread soft-stop on time window'.

doc/configuration.txt
include/haproxy/global-t.h
src/mux_h1.c
src/mux_h2.c
src/proxy.c

index 9461b9b904bf55ac95923a81656babbbc16da1aa..4f7fc4afb441ad5cdeac2316cc7dd306ecdbb487 100644 (file)
@@ -1165,16 +1165,22 @@ close-spread-time <time>
   close" line to the HTTP response, or by sending a GOAWAY frame in case of
   HTTP2. When this option is set, connection closing will be spread over this
   set <time>.
+  If the close-spread-time is set to "infinite", active connection closing
+  during a soft-stop will be disabled. The "Connection: close" header will not
+  be added to HTTP responses (or GOAWAY for HTTP2) anymore and idle connections
+  will only be closed once their timeout is reached (based on the various
+  timeouts set in the configuration).
 
   Arguments :
     <time>  is a time window (by default in milliseconds) during which
-            connection closing will be spread during a soft-stop operation.
+            connection closing will be spread during a soft-stop operation, or
+            "infinite" if active connection closing should be disabled.
 
   It is recommended to set this setting to a value lower than the one used in
   the "hard-stop-after" option if this one is used, so that all connections
   have a chance to gracefully close before the process stops.
 
-  See also: grace, hard-stop-after
+  See also: grace, hard-stop-after, idle-close-on-response
 
 cpu-map [auto:]<process-set>[/<thread-set>] <cpu-set>...
   On some operating systems, it is possible to bind a process or a thread to a
index c188cb38cbfcd7463ceb255f1b73f00ccd4090b1..7b8c2e6b82ded1b14225fb7c0bd9e862b22cbef4 100644 (file)
@@ -74,6 +74,7 @@
 #define GTUNE_SCHED_LOW_LATENCY  (1<<19)
 #define GTUNE_IDLE_POOL_SHARED   (1<<20)
 #define GTUNE_DISABLE_H2_WEBSOCKET (1<<21)
+#define GTUNE_DISABLE_ACTIVE_CLOSE (1<<22)
 
 /* SSL server verify mode */
 enum {
index bdbd61fb19d84f04aa7844f3a4dc545c93b71262..6e9e50ea2fee2ea985cce21753387b3220d22e0f 100644 (file)
@@ -1198,7 +1198,9 @@ static void h1_set_cli_conn_mode(struct h1s *h1s, struct h1m *h1m)
        }
 
        /* If KAL, check if the frontend is stopping. If yes, switch in CLO mode
-        * unless a 'close-spread-time' option is set.
+        * unless a 'close-spread-time' option is set (either to define a
+        * soft-close window or to disable active closing (close-spread-time
+        * option set to 0).
         */
        if (h1s->flags & H1S_F_WANT_KAL && (fe->flags & (PR_FL_DISABLED|PR_FL_STOPPED))) {
                int want_clo = 1;
@@ -1215,6 +1217,8 @@ static void h1_set_cli_conn_mode(struct h1s *h1s, struct h1m *h1m)
                                want_clo = (remaining_window <= statistical_prng_range(global.close_spread_time));
                        }
                }
+               else if (global.tune.options & GTUNE_DISABLE_ACTIVE_CLOSE)
+                       want_clo = 0;
 
                if (want_clo) {
                        h1s->flags = (h1s->flags & ~H1S_F_WANT_MSK) | H1S_F_WANT_CLO;
@@ -3088,6 +3092,8 @@ static int h1_process(struct h1c * h1c)
                                                send_close = (remaining_window <= statistical_prng_range(global.close_spread_time));
                                        }
                                }
+                               else if (global.tune.options & GTUNE_DISABLE_ACTIVE_CLOSE)
+                                       send_close = 0; /* let the client close his connection himself */
                                if (send_close)
                                        goto release;
                        }
index 4bacc8c2fbfbbb8424a007f93715dcbf32cc1258..20193d4e6435f3cdae0566131b1b1cc5b705d175 100644 (file)
@@ -4059,6 +4059,8 @@ static int h2_process(struct h2c *h2c)
                                send_goaway = (remaining_window <= statistical_prng_range(global.close_spread_time));
                        }
                }
+               else if (global.tune.options & GTUNE_DISABLE_ACTIVE_CLOSE)
+                       send_goaway = 0; /* let the client close his connection himself */
                /* frontend is stopping, reload likely in progress, let's try
                 * to announce a graceful shutdown if not yet done. We don't
                 * care if it fails, it will be tried again later.
index ba32f94194168d22a8083aa5d39020849ed7553c..8b2299ce0f1cf8d3449571b0c94086be7b9eebfc 100644 (file)
@@ -2087,6 +2087,16 @@ static int proxy_parse_close_spread_time(char **args, int section_type, struct p
                memprintf(err, "'%s' expects <time> as argument.\n", args[0]);
                return -1;
        }
+
+       /* If close-spread-time is set to "infinite", disable the active connection
+        * closing during soft-stop.
+        */
+       if (strcmp(args[1], "infinite") == 0) {
+               global.tune.options |= GTUNE_DISABLE_ACTIVE_CLOSE;
+               global.close_spread_time = TICK_ETERNITY;
+               return 0;
+       }
+
        res = parse_time_err(args[1], &global.close_spread_time, TIME_UNIT_MS);
        if (res == PARSE_TIME_OVER) {
                memprintf(err, "timer overflow in argument '%s' to '%s' (maximum value is 2147483647 ms or ~24.8 days)",
@@ -2102,6 +2112,8 @@ static int proxy_parse_close_spread_time(char **args, int section_type, struct p
                memprintf(err, "unexpected character '%c' in argument to <%s>.\n", *res, args[0]);
                return -1;
        }
+       global.tune.options &= ~GTUNE_DISABLE_ACTIVE_CLOSE;
+
        return 0;
 }