This is very useful in complex architecture systems where HAproxy
is balancing DB connections for example. We want to keep the maxconn
high in order to avoid issues with queueing on the LB level when
there is slowness on another part of the system. Example is a case of
an architecture where each thread opens multiple DB connections, which
if get stuck in queue cause a snowball effect (old connections aren't
closed, new ones cannot be established). These connections are mostly
idle and the DB server has no problem handling thousands of them.
Allowing us to dynamically set maxconn depending on the backend usage
(LA, CPU, memory, etc.) enables us to have high maxconn for situations
like above, but lowering it in case there are real issues where the
backend servers become overloaded (cache issues, DB gets hit hard).
---
doc/configuration.txt | 3 +++
include/proto/server.h | 8 ++++++++
src/checks.c | 18 +++++++++++++++++-
src/server.c | 27 +++++++++++++++++++++++++++
4 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index c705a09..640c0f3 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -10146,6 +10146,9 @@ agent-check
weight is reported on the stats page as "DRAIN" since it has the same
effect on the server (it's removed from the LB farm).
+ - An ASCII representation of a positive integer, followed by a single letter
+ 'm'. Values in this format will set the maxconn of a server.
+
- The word "ready". This will turn the server's administrative state to the
READY mode, thus cancelling any DRAIN or MAINT state
diff --git a/include/proto/server.h b/include/proto/server.h
index 872503c..176851a 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -113,6 +113,14 @@ const char *server_parse_addr_change_request(struct server *sv,
const char *addr_str, const char *updater);
/*
+ * Parses maxconn_str and configures sv accordingly.
+ * Returns NULL on success, error message string otherwise.
+ */
+const char *server_parse_maxconn_change_request(struct server *sv,
+ const char *maxconn_str);
+
+
+/*
* Return true if the server has a zero user-weight, meaning it's in draining
* mode (ie: not taking new non-persistent connections).
*/
diff --git a/src/checks.c b/src/checks.c
index 35fd020..f3f767d 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -938,6 +938,7 @@ static void event_srv_chk_r(struct connection *conn)
const char *hs = NULL; /* health status */
const char *as = NULL; /* admin status */
const char *ps = NULL; /* performance status */
+ const char *cs = NULL; /* maxconn */
const char *err = NULL; /* first error to report */
const char *wrn = NULL; /* first warning to report */
char *cmd, *p;
@@ -1039,10 +1040,14 @@ static void event_srv_chk_r(struct connection *conn)
else if (strcasecmp(cmd, "maint") == 0) {
as = cmd;
}
- /* else try to parse a weight here and keep the last one */
+ /* try to parse a weight here and keep the last one */
else if (isdigit((unsigned char)*cmd) && strchr(cmd, '%') != NULL) {
ps = cmd;
}
+ /* try to parse a maxconn here */
+ else if (isdigit((unsigned char)*cmd) && strchr(cmd, 'm') != NULL) {
+ cs = cmd;
+ }
else {
/* keep a copy of the first error */
if (!err)
@@ -1079,6 +1084,17 @@ static void event_srv_chk_r(struct connection *conn)
wrn = msg;
}
+ if (cs) {
+ const char *msg;
+
+ /* Remove character 'm' before setting maxconn */
+ *strchr(cs, 'm') = '\0';
+
+ msg = server_parse_maxconn_change_request(s, cs);
+ if (!wrn || !*wrn)
+ wrn = msg;
+ }
+
/* and finally health status */
if (hs) {
/* We'll report some of the warnings and errors we have
diff --git a/src/server.c b/src/server.c
index 5a2c58a..1095754 100644
--- a/src/server.c
+++ b/src/server.c
@@ -831,6 +831,33 @@ const char *server_parse_addr_change_request(struct server *sv,
return "Could not understand IP address format.\n";
}
+const char *server_parse_maxconn_change_request(struct server *sv,
+ const char *maxconn_str)
+{
+ long int v;
+ char *end;
+
+ if (!*maxconn_str)
+ return "Require <maxconn>.\n";
+
+ v = strtol(maxconn_str, &end, 10);
+ if (end == maxconn_str)
+ return "maxconn string empty or preceded by garbage";
+ else if (end[0] != '\0')
+ return "Trailing garbage in maxconn string";
+
+ if (sv->maxconn == sv->minconn) { // static maxconn
+ sv->maxconn = sv->minconn = v;
+ } else { // dynamic maxconn
+ sv->maxconn = v;
+ }
+
+ if (may_dequeue_tasks(sv, sv->proxy))
+ process_srv_queue(sv);
+
+ return NULL;
+}
+
int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
{
struct server *newsrv = NULL;
--
2.7.0
is balancing DB connections for example. We want to keep the maxconn
high in order to avoid issues with queueing on the LB level when
there is slowness on another part of the system. Example is a case of
an architecture where each thread opens multiple DB connections, which
if get stuck in queue cause a snowball effect (old connections aren't
closed, new ones cannot be established). These connections are mostly
idle and the DB server has no problem handling thousands of them.
Allowing us to dynamically set maxconn depending on the backend usage
(LA, CPU, memory, etc.) enables us to have high maxconn for situations
like above, but lowering it in case there are real issues where the
backend servers become overloaded (cache issues, DB gets hit hard).
---
doc/configuration.txt | 3 +++
include/proto/server.h | 8 ++++++++
src/checks.c | 18 +++++++++++++++++-
src/server.c | 27 +++++++++++++++++++++++++++
4 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/doc/configuration.txt b/doc/configuration.txt
index c705a09..640c0f3 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -10146,6 +10146,9 @@ agent-check
weight is reported on the stats page as "DRAIN" since it has the same
effect on the server (it's removed from the LB farm).
+ - An ASCII representation of a positive integer, followed by a single letter
+ 'm'. Values in this format will set the maxconn of a server.
+
- The word "ready". This will turn the server's administrative state to the
READY mode, thus cancelling any DRAIN or MAINT state
diff --git a/include/proto/server.h b/include/proto/server.h
index 872503c..176851a 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -113,6 +113,14 @@ const char *server_parse_addr_change_request(struct server *sv,
const char *addr_str, const char *updater);
/*
+ * Parses maxconn_str and configures sv accordingly.
+ * Returns NULL on success, error message string otherwise.
+ */
+const char *server_parse_maxconn_change_request(struct server *sv,
+ const char *maxconn_str);
+
+
+/*
* Return true if the server has a zero user-weight, meaning it's in draining
* mode (ie: not taking new non-persistent connections).
*/
diff --git a/src/checks.c b/src/checks.c
index 35fd020..f3f767d 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -938,6 +938,7 @@ static void event_srv_chk_r(struct connection *conn)
const char *hs = NULL; /* health status */
const char *as = NULL; /* admin status */
const char *ps = NULL; /* performance status */
+ const char *cs = NULL; /* maxconn */
const char *err = NULL; /* first error to report */
const char *wrn = NULL; /* first warning to report */
char *cmd, *p;
@@ -1039,10 +1040,14 @@ static void event_srv_chk_r(struct connection *conn)
else if (strcasecmp(cmd, "maint") == 0) {
as = cmd;
}
- /* else try to parse a weight here and keep the last one */
+ /* try to parse a weight here and keep the last one */
else if (isdigit((unsigned char)*cmd) && strchr(cmd, '%') != NULL) {
ps = cmd;
}
+ /* try to parse a maxconn here */
+ else if (isdigit((unsigned char)*cmd) && strchr(cmd, 'm') != NULL) {
+ cs = cmd;
+ }
else {
/* keep a copy of the first error */
if (!err)
@@ -1079,6 +1084,17 @@ static void event_srv_chk_r(struct connection *conn)
wrn = msg;
}
+ if (cs) {
+ const char *msg;
+
+ /* Remove character 'm' before setting maxconn */
+ *strchr(cs, 'm') = '\0';
+
+ msg = server_parse_maxconn_change_request(s, cs);
+ if (!wrn || !*wrn)
+ wrn = msg;
+ }
+
/* and finally health status */
if (hs) {
/* We'll report some of the warnings and errors we have
diff --git a/src/server.c b/src/server.c
index 5a2c58a..1095754 100644
--- a/src/server.c
+++ b/src/server.c
@@ -831,6 +831,33 @@ const char *server_parse_addr_change_request(struct server *sv,
return "Could not understand IP address format.\n";
}
+const char *server_parse_maxconn_change_request(struct server *sv,
+ const char *maxconn_str)
+{
+ long int v;
+ char *end;
+
+ if (!*maxconn_str)
+ return "Require <maxconn>.\n";
+
+ v = strtol(maxconn_str, &end, 10);
+ if (end == maxconn_str)
+ return "maxconn string empty or preceded by garbage";
+ else if (end[0] != '\0')
+ return "Trailing garbage in maxconn string";
+
+ if (sv->maxconn == sv->minconn) { // static maxconn
+ sv->maxconn = sv->minconn = v;
+ } else { // dynamic maxconn
+ sv->maxconn = v;
+ }
+
+ if (may_dequeue_tasks(sv, sv->proxy))
+ process_srv_queue(sv);
+
+ return NULL;
+}
+
int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
{
struct server *newsrv = NULL;
--
2.7.0