]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mpm_event: Restart stopping of idle children after a load peak. PR 65626.
authorYann Ylavic <ylavic@apache.org>
Fri, 15 Oct 2021 10:29:00 +0000 (10:29 +0000)
committerYann Ylavic <ylavic@apache.org>
Fri, 15 Oct 2021 10:29:00 +0000 (10:29 +0000)
r1770752 added an heuristic to avoid stopping children when the load triggers
MaxSpareThreads but children take some time to shut down until the point where
active_daemons_limit/ServerLimit is reached (scoreboard full) and no child gets
created to handle incoming connections.

However when this happens there is nothing to stop children again when the load
settles down (besides MaxRequestsPerChild, which may be 0) so let's restart to
stop children again if/when idle_thread_count reaches max_workers / 4.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1894285 13f79535-47bb-0310-9956-ffa450edef68

changes-entries/event-kill_at_total_daemons_limit.txt [new file with mode: 0644]
server/mpm/event/event.c

diff --git a/changes-entries/event-kill_at_total_daemons_limit.txt b/changes-entries/event-kill_at_total_daemons_limit.txt
new file mode 100644 (file)
index 0000000..007e961
--- /dev/null
@@ -0,0 +1,2 @@
+  *) mpm_event: Restart stopping of idle children after a load peak. PR 65626.
+     [Yann Ylavic, Ruediger Pluem]
index aa6304042a6be20b729021960f83ee040ed3ef9a..2e7bb6bfdbdbf27f40cb6d6901d084c2c0c9fef3 100644 (file)
@@ -3187,7 +3187,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
          * gracefully finishing processes may accumulate, filling up the
          * scoreboard. To avoid running out of scoreboard entries, we
          * don't shut down more processes when the total number of processes
-         * is high.
+         * is high, until there are more than max_workers/4 idle threads.
          *
          * XXX It would be nice if we could
          * XXX - kill processes without keepalive connections first
@@ -3195,13 +3195,19 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
          * XXX   depending on server load, later be able to resurrect them
          *       or kill them
          */
-        if (retained->total_daemons <= active_daemons_limit &&
-            retained->total_daemons < server_limit) {
+        if ((retained->total_daemons <= active_daemons_limit
+             && retained->total_daemons < server_limit)
+            /* The above test won't transition from true to false until a child
+             * exits by itself (i.e. MaxRequestsPerChild reached), so the below
+             * test makes sure that the situation unblocks when the load falls
+             * significantly (regardless of MaxRequestsPerChild, e.g. 0) */
+            || idle_thread_count > max_workers/4 / num_buckets) {
             /* Kill off one child */
             ap_mpm_podx_signal(retained->buckets[child_bucket].pod,
                                AP_MPM_PODX_GRACEFUL);
             retained->idle_spawn_rate[child_bucket] = 1;
         } else {
+            /* Still busy enough, don't kill */
             ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf,
                          "Not shutting down child: total daemons %d / "
                          "active limit %d / ServerLimit %d",