From 4f9e7cf5d7dda9011afee1b886f5c27eec77d148 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Fri, 15 Oct 2021 10:29:00 +0000 Subject: [PATCH] mpm_event: Restart stopping of idle children after a load peak. PR 65626. 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 --- .../event-kill_at_total_daemons_limit.txt | 2 ++ server/mpm/event/event.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 changes-entries/event-kill_at_total_daemons_limit.txt 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 index 00000000000..007e9615e2f --- /dev/null +++ b/changes-entries/event-kill_at_total_daemons_limit.txt @@ -0,0 +1,2 @@ + *) mpm_event: Restart stopping of idle children after a load peak. PR 65626. + [Yann Ylavic, Ruediger Pluem] diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index aa6304042a6..2e7bb6bfdbd 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -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", -- 2.47.3