From acde15217550f6db198b0119e743222b40ce5245 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 7 Oct 2020 16:31:39 +0200 Subject: [PATCH] MEDIUM: proxy: centralize proxy status update and reporting There are multiple ways a proxy may switch to the disabled state, but now it's essentially once it loses its last listener. Instead of keeping duplicate code around and reporting the state change before actually seeing it, we now report it at the moment it's performed (from the last listener leaving) which allows to remove the message from all other places. --- include/haproxy/proxy.h | 1 + src/listener.c | 6 +---- src/proxy.c | 49 +++++++++++++++++++++++++++++++++-------- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/include/haproxy/proxy.h b/include/haproxy/proxy.h index a33ed26ee..fe253bf7f 100644 --- a/include/haproxy/proxy.h +++ b/include/haproxy/proxy.h @@ -40,6 +40,7 @@ extern const struct cfg_opt cfg_opts[]; extern const struct cfg_opt cfg_opts2[]; struct task *manage_proxy(struct task *t, void *context, unsigned short state); +void proxy_cond_disable(struct proxy *p); void soft_stop(void); int pause_proxy(struct proxy *p); int resume_proxy(struct proxy *p); diff --git a/src/listener.c b/src/listener.c index e8f2a95b6..6368e37b6 100644 --- a/src/listener.c +++ b/src/listener.c @@ -354,11 +354,7 @@ void stop_listener(struct listener *l, int lpx, int lpr, int lli) if (l->state >= LI_ASSIGNED) __delete_listener(l); - if (px->li_ready + px->li_paused == 0) { - px->disabled = 1; - if (px->task) - task_wakeup(px->task, TASK_WOKEN_MSG); - } + proxy_cond_disable(px); } if (!lli) diff --git a/src/proxy.c b/src/proxy.c index 247ee6366..a77ad0a8f 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1045,6 +1045,46 @@ void init_new_proxy(struct proxy *p) HA_SPIN_INIT(&p->lock); } +/* to be called under the proxy lock after stopping some listeners. This will + * automatically update the p->disabled flag after stopping the last one, and + * will emit a log indicating the proxy's condition. The function is idempotent + * so that it will not emit multiple logs; a proxy will be disabled only once. + */ +void proxy_cond_disable(struct proxy *p) +{ + if (p->disabled) + return; + + if (p->li_ready + p->li_paused > 0) + return; + + p->disabled = 1; + + if (!(proc_mask(p->bind_proc) & pid_bit)) + goto silent; + + /* Note: syslog proxies use their own loggers so while it's somewhat OK + * to report them being stopped as a warning, we must not spam their log + * servers which are in fact production servers. For other types (CLI, + * peers, etc) we must not report them at all as they're not really on + * the data plane but on the control plane. + */ + if (p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP || p->mode == PR_MODE_SYSLOG) + ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", + p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn); + + if (p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP) + send_log(p, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", + p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn); + + silent: + if (p->table && p->table->size && p->table->sync_task) + task_wakeup(p->table->sync_task, TASK_WOKEN_MSG); + + if (p->task) + task_wakeup(p->task, TASK_WOKEN_MSG); +} + /* * This is the proxy management task. It enables proxies when there are enough * free streams, or stops them when the table is full. It is designed to be @@ -1066,10 +1106,6 @@ struct task *manage_proxy(struct task *t, void *context, unsigned short state) int t; t = tick_remain(now_ms, p->stop_time); if (t == 0) { - ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", - p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn); - send_log(p, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", - p->id, p->fe_counters.cum_conn, p->be_counters.cum_conn); stop_proxy(p); /* try to free more memory */ pool_gc(NULL); @@ -2069,11 +2105,6 @@ static int cli_parse_shutdown_frontend(char **args, char *payload, struct appctx if (px->disabled) return cli_msg(appctx, LOG_NOTICE, "Frontend was already shut down.\n"); - ha_warning("Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", - px->id, px->fe_counters.cum_conn, px->be_counters.cum_conn); - send_log(px, LOG_WARNING, "Proxy %s stopped (cumulated conns: FE: %lld, BE: %lld).\n", - px->id, px->fe_counters.cum_conn, px->be_counters.cum_conn); - stop_proxy(px); return 1; }