From 4b2674e20b620df36e960392aacd6d879cf61d5d Mon Sep 17 00:00:00 2001 From: xh Date: Mon, 23 Jun 2025 09:52:14 +0800 Subject: [PATCH] fix slowstart behavior (cherry picked from commit d3e92a7d89670ccdf87905015b8269b0f4f9e848) --- ...-MINOR-server-fix-slowstart-behavior.patch | 76 +++++++++++++++++++ haproxy.spec | 9 ++- 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 backport-BUG-MINOR-server-fix-slowstart-behavior.patch diff --git a/backport-BUG-MINOR-server-fix-slowstart-behavior.patch b/backport-BUG-MINOR-server-fix-slowstart-behavior.patch new file mode 100644 index 0000000..06d9fca --- /dev/null +++ b/backport-BUG-MINOR-server-fix-slowstart-behavior.patch @@ -0,0 +1,76 @@ +From a6c0926ba1ca5eac00b0bcd25934f89b9693ddb0 Mon Sep 17 00:00:00 2001 +From: Damien Claisse +Date: Tue, 9 Apr 2024 15:37:07 +0000 +Subject: [PATCH] BUG/MINOR: server: fix slowstart behavior + +We observed that a dynamic server which health check is down for longer +than slowstart delay at startup doesn't trigger the warmup phase, it +receives full traffic immediately. This has been confirmed by checking +haproxy UI, weight is immediately the full one (e.g. 75/75), without any +throttle applied. Further tests showed that it was similar if it was in +maintenance, and even when entering a down or maintenance state after +being up. +Another issue is that if the server is down for less time than +slowstart, when it comes back up, it briefly has a much higher weight +than expected for a slowstart. + +An easy way to reproduce is to do the following: +- Add a server with e.g. a 20s slowstart and a weight of 10 in config + file +- Put it in maintenance using CLI (set server be1/srv1 state maint) +- Wait more than 20s, enable it again (set server be1/srv1 state ready) +- Observe UI, weight will show 10/10 immediately. +If server was down for less than 20s, you'd briefly see a weight and +throttle value that is inconsistent, e.g. 50% throttle value and a +weight of 5 if server comes back up after 10s before going back to +6% after a second or two. + +Code analysis shows that the logic in server_recalc_eweight stops the +warmup task by setting server's next state to SRV_ST_RUNNING if it +didn't change state for longer than the slowstart duration, regardless +of its current state. As a consequence, a server being down or disabled +for longer than the slowstart duration will never enter the warmup phase +when it will be up again. + +Regarding the weight when server comes back up, issue is that even if +the server is down, we still compute its next weight as if it was up, +hence when it comes back up, it can briefly have a much higher weight +than expected during slowstart, until the warmup task is called again +after last_change is updated. + +This patch aims to fix both issues. + +(cherry picked from commit 0797e05d9f0577d9239d4265667ea536a2439db0) +Signed-off-by: Christopher Faulet + +Conflict: NA +Reference:https://github.com/haproxy/haproxy/commit/a6c0926ba1ca5eac00b0bcd25934f89b9693ddb0 +--- + src/server.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/server.c b/src/server.c +index 7655b3315f4ee..fc7fde608e5ea 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -2291,15 +2291,17 @@ void server_recalc_eweight(struct server *sv, int must_update) + unsigned w; + + if (ns_to_sec(now_ns) < sv->last_change || ns_to_sec(now_ns) >= sv->last_change + sv->slowstart) { +- /* go to full throttle if the slowstart interval is reached */ +- if (sv->next_state == SRV_ST_STARTING) ++ /* go to full throttle if the slowstart interval is reached unless server is currently down */ ++ if ((sv->cur_state != SRV_ST_STOPPED) && (sv->next_state == SRV_ST_STARTING)) + sv->next_state = SRV_ST_RUNNING; + } + + /* We must take care of not pushing the server to full throttle during slow starts. + * It must also start immediately, at least at the minimal step when leaving maintenance. + */ +- if ((sv->next_state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN)) ++ if ((sv->cur_state == SRV_ST_STOPPED) && (sv->next_state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN)) ++ w = 1; ++ else if ((sv->next_state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN)) + w = (px->lbprm.wdiv * (ns_to_sec(now_ns) - sv->last_change) + sv->slowstart) / sv->slowstart; + else + w = px->lbprm.wdiv; diff --git a/haproxy.spec b/haproxy.spec index 2aefd22..f7e1dcc 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -5,7 +5,7 @@ Name: haproxy Version: 2.9.5 -Release: 9 +Release: 10 Summary: The Reliable, High Performance TCP/HTTP Load Balancer License: GPLv2+ @@ -26,6 +26,7 @@ Patch7: backport-BUG-MEDIUM-queues-Do-not-use-pendconn_grab_from_px.pa Patch8: backport-BUG-MEDIUM-queues-Make-sure-we-call-process_srv_queu.patch Patch9: backport-BUG-MEDIUM-queue-Make-process_srv_queue-return-the-n.patch Patch10: backport-CVE-2025-32464.patch +Patch11: backport-BUG-MINOR-server-fix-slowstart-behavior.patch BuildRequires: gcc lua-devel pcre2-devel openssl-devel systemd-devel systemd libatomic Requires(pre): shadow-utils @@ -130,6 +131,12 @@ exit 0 %{_mandir}/man1/* %changelog +* Mon Jun 23 2025 xinghe - 2.9.5-10 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:fix slowstart behavior + * Tue Apr 29 2025 xinghe - 2.9.5-9 - Type:cves - CVE:CVE-2025-32464 -- Gitee