mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-26 14:42:21 +00:00
MEDIUM: servers: Add a command to limit the number of idling connections.
Add a new command, "pool-max-conn" that sets the maximum number of connections waiting in the orphan idling connections list (as activated with idle-timeout). Using "-1" means unlimited. Using pools is now dependant on this.
This commit is contained in:
parent
86006a561e
commit
006e3101f9
@ -11972,6 +11972,14 @@ on-marked-up <action>
|
|||||||
|
|
||||||
Actions are disabled by default
|
Actions are disabled by default
|
||||||
|
|
||||||
|
pool-max-conn <max>
|
||||||
|
Set the maximum number of idling connections for a server. -1 means unlimited
|
||||||
|
connections, 0 means no idle connections. The default is -1. When idle
|
||||||
|
connections are enabled, orphaned idle connections which do not belong to any
|
||||||
|
client session anymore are moved to a dedicated pool so that they remain
|
||||||
|
usable by future clients. This only applies to connections that can be shared
|
||||||
|
according to the same principles as those applying to "http-reuse".
|
||||||
|
|
||||||
port <port>
|
port <port>
|
||||||
Using the "port" parameter, it becomes possible to use a different port to
|
Using the "port" parameter, it becomes possible to use a different port to
|
||||||
send health-checks. On some servers, it may be desirable to dedicate a port
|
send health-checks. On some servers, it may be desirable to dedicate a port
|
||||||
|
@ -558,6 +558,7 @@ static inline void conn_init(struct connection *conn)
|
|||||||
LIST_INIT(&conn->session_list);
|
LIST_INIT(&conn->session_list);
|
||||||
conn->send_wait = NULL;
|
conn->send_wait = NULL;
|
||||||
conn->recv_wait = NULL;
|
conn->recv_wait = NULL;
|
||||||
|
conn->idle_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sets <owner> as the connection's owner */
|
/* sets <owner> as the connection's owner */
|
||||||
@ -673,6 +674,13 @@ static inline void conn_free(struct connection *conn)
|
|||||||
if (objt_conn(s->si[1].end) == conn)
|
if (objt_conn(s->si[1].end) == conn)
|
||||||
s->si[1].end = NULL;
|
s->si[1].end = NULL;
|
||||||
}
|
}
|
||||||
|
/* The connection is currently in the server's idle list, so tell it
|
||||||
|
* there's one less connection available in that list.
|
||||||
|
*/
|
||||||
|
if (conn->idle_time > 0) {
|
||||||
|
struct server *srv = __objt_server(conn->target);
|
||||||
|
srv->curr_idle_conns--;
|
||||||
|
}
|
||||||
|
|
||||||
conn_force_unsubscribe(conn);
|
conn_force_unsubscribe(conn);
|
||||||
LIST_DEL(&conn->list);
|
LIST_DEL(&conn->list);
|
||||||
|
@ -446,7 +446,7 @@ struct connection {
|
|||||||
struct sockaddr_storage from; /* client address, or address to spoof when connecting to the server */
|
struct sockaddr_storage from; /* client address, or address to spoof when connecting to the server */
|
||||||
struct sockaddr_storage to; /* address reached by the client, or address to connect to */
|
struct sockaddr_storage to; /* address reached by the client, or address to connect to */
|
||||||
} addr; /* addresses of the remote side, client for producer and server for consumer */
|
} addr; /* addresses of the remote side, client for producer and server for consumer */
|
||||||
unsigned int idle_time; /* Time the connection was added to the idle list */
|
unsigned int idle_time; /* Time the connection was added to the idle list, or 0 if not in the idle list */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PROTO token registration */
|
/* PROTO token registration */
|
||||||
|
@ -223,6 +223,8 @@ struct server {
|
|||||||
struct list *safe_conns; /* safe idle connections attached to stream interfaces, shared */
|
struct list *safe_conns; /* safe idle connections attached to stream interfaces, shared */
|
||||||
struct list *idle_orphan_conns; /* Orphan connections idling */
|
struct list *idle_orphan_conns; /* Orphan connections idling */
|
||||||
unsigned int idle_timeout; /* Time to keep an idling orphan connection alive */
|
unsigned int idle_timeout; /* Time to keep an idling orphan connection alive */
|
||||||
|
unsigned int max_idle_conns; /* Max number of connection allowed in the orphan connections list */
|
||||||
|
unsigned int curr_idle_conns; /* Current number of orphan idling connections */
|
||||||
struct task **idle_task; /* task responsible for cleaning idle orphan connections */
|
struct task **idle_task; /* task responsible for cleaning idle orphan connections */
|
||||||
struct task *warmup; /* the task dedicated to the warmup when slowstart is set */
|
struct task *warmup; /* the task dedicated to the warmup when slowstart is set */
|
||||||
|
|
||||||
|
@ -1231,6 +1231,8 @@ int connect_server(struct stream *s)
|
|||||||
*/
|
*/
|
||||||
if (reuse && reuse_orphan) {
|
if (reuse && reuse_orphan) {
|
||||||
LIST_DEL(&srv_conn->list);
|
LIST_DEL(&srv_conn->list);
|
||||||
|
srv_conn->idle_time = 0;
|
||||||
|
srv->curr_idle_conns--;
|
||||||
LIST_ADDQ(&srv->idle_conns[tid], &srv_conn->list);
|
LIST_ADDQ(&srv->idle_conns[tid], &srv_conn->list);
|
||||||
if (LIST_ISEMPTY(&srv->idle_orphan_conns[tid]))
|
if (LIST_ISEMPTY(&srv->idle_orphan_conns[tid]))
|
||||||
task_unlink_wq(srv->idle_task[tid]);
|
task_unlink_wq(srv->idle_task[tid]);
|
||||||
|
@ -471,6 +471,7 @@ void init_default_instance()
|
|||||||
defproxy.defsrv.maxqueue = 0;
|
defproxy.defsrv.maxqueue = 0;
|
||||||
defproxy.defsrv.minconn = 0;
|
defproxy.defsrv.minconn = 0;
|
||||||
defproxy.defsrv.maxconn = 0;
|
defproxy.defsrv.maxconn = 0;
|
||||||
|
defproxy.defsrv.max_idle_conns = -1;
|
||||||
defproxy.defsrv.slowstart = 0;
|
defproxy.defsrv.slowstart = 0;
|
||||||
defproxy.defsrv.onerror = DEF_HANA_ONERR;
|
defproxy.defsrv.onerror = DEF_HANA_ONERR;
|
||||||
defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
|
defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
|
||||||
|
23
src/server.c
23
src/server.c
@ -380,6 +380,20 @@ static int srv_parse_idle_timeout(char **args, int *cur_arg, struct proxy *curpr
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int srv_parse_pool_max_conn(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err)
|
||||||
|
{
|
||||||
|
char *arg;
|
||||||
|
|
||||||
|
arg = args[*cur_arg + 1];
|
||||||
|
if (!*arg) {
|
||||||
|
memprintf(err, "'%s' expects <value> as argument.\n", args[*cur_arg]);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
newsrv->max_idle_conns = atoi(arg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse the "id" server keyword */
|
/* parse the "id" server keyword */
|
||||||
static int srv_parse_id(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err)
|
static int srv_parse_id(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err)
|
||||||
{
|
{
|
||||||
@ -1230,6 +1244,7 @@ static struct srv_kw_list srv_kws = { "ALL", { }, {
|
|||||||
{ "no-send-proxy-v2", srv_parse_no_send_proxy_v2, 0, 1 }, /* Disable use of PROXY V2 protocol */
|
{ "no-send-proxy-v2", srv_parse_no_send_proxy_v2, 0, 1 }, /* Disable use of PROXY V2 protocol */
|
||||||
{ "non-stick", srv_parse_non_stick, 0, 1 }, /* Disable stick-table persistence */
|
{ "non-stick", srv_parse_non_stick, 0, 1 }, /* Disable stick-table persistence */
|
||||||
{ "observe", srv_parse_observe, 1, 1 }, /* Enables health adjusting based on observing communication with the server */
|
{ "observe", srv_parse_observe, 1, 1 }, /* Enables health adjusting based on observing communication with the server */
|
||||||
|
{ "pool-max-conn", srv_parse_pool_max_conn, 1, 1 }, /* Set the max number of orphan idle connections, 0 means unlimited */
|
||||||
{ "proto", srv_parse_proto, 1, 1 }, /* Set the proto to use for all outgoing connections */
|
{ "proto", srv_parse_proto, 1, 1 }, /* Set the proto to use for all outgoing connections */
|
||||||
{ "proxy-v2-options", srv_parse_proxy_v2_options, 1, 1 }, /* options for send-proxy-v2 */
|
{ "proxy-v2-options", srv_parse_proxy_v2_options, 1, 1 }, /* options for send-proxy-v2 */
|
||||||
{ "redir", srv_parse_redir, 1, 1 }, /* Enable redirection mode */
|
{ "redir", srv_parse_redir, 1, 1 }, /* Enable redirection mode */
|
||||||
@ -1665,6 +1680,7 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp
|
|||||||
#endif
|
#endif
|
||||||
srv->mux_proto = src->mux_proto;
|
srv->mux_proto = src->mux_proto;
|
||||||
srv->idle_timeout = src->idle_timeout;
|
srv->idle_timeout = src->idle_timeout;
|
||||||
|
srv->max_idle_conns = src->max_idle_conns;
|
||||||
|
|
||||||
if (srv_tmpl)
|
if (srv_tmpl)
|
||||||
srv->srvrq = src->srvrq;
|
srv->srvrq = src->srvrq;
|
||||||
@ -1708,6 +1724,9 @@ struct server *new_server(struct proxy *proxy)
|
|||||||
srv->agent.server = srv;
|
srv->agent.server = srv;
|
||||||
srv->xprt = srv->check.xprt = srv->agent.xprt = xprt_get(XPRT_RAW);
|
srv->xprt = srv->check.xprt = srv->agent.xprt = xprt_get(XPRT_RAW);
|
||||||
|
|
||||||
|
srv->idle_timeout = 1000;
|
||||||
|
srv->max_idle_conns = -1;
|
||||||
|
|
||||||
return srv;
|
return srv;
|
||||||
|
|
||||||
free_idle_conns:
|
free_idle_conns:
|
||||||
@ -1914,7 +1933,7 @@ static int server_finalize_init(const char *file, int linenum, char **args, int
|
|||||||
px->srv_act++;
|
px->srv_act++;
|
||||||
srv_lb_commit_status(srv);
|
srv_lb_commit_status(srv);
|
||||||
|
|
||||||
if (!srv->tmpl_info.prefix && srv->idle_timeout != 0) {
|
if (!srv->tmpl_info.prefix && srv->max_idle_conns != 0) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
srv->idle_orphan_conns = calloc(global.nbthread, sizeof(*srv->idle_orphan_conns));
|
srv->idle_orphan_conns = calloc(global.nbthread, sizeof(*srv->idle_orphan_conns));
|
||||||
@ -2019,7 +2038,7 @@ static int server_template_init(struct server *srv, struct proxy *px)
|
|||||||
/* Linked backwards first. This will be restablished after parsing. */
|
/* Linked backwards first. This will be restablished after parsing. */
|
||||||
newsrv->next = px->srv;
|
newsrv->next = px->srv;
|
||||||
px->srv = newsrv;
|
px->srv = newsrv;
|
||||||
if (newsrv->idle_timeout != 0) {
|
if (newsrv->max_idle_conns != 0) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
newsrv->idle_orphan_conns = calloc(global.nbthread, sizeof(*newsrv->idle_orphan_conns));
|
newsrv->idle_orphan_conns = calloc(global.nbthread, sizeof(*newsrv->idle_orphan_conns));
|
||||||
|
@ -93,6 +93,8 @@ void session_free(struct session *sess)
|
|||||||
srv = objt_server(conn->target);
|
srv = objt_server(conn->target);
|
||||||
conn->owner = NULL;
|
conn->owner = NULL;
|
||||||
if (srv && srv->idle_timeout > 0 &&
|
if (srv && srv->idle_timeout > 0 &&
|
||||||
|
(srv->max_idle_conns == -1 ||
|
||||||
|
srv->max_idle_conns > srv->curr_idle_conns) &&
|
||||||
!(conn->flags & CO_FL_PRIVATE) &&
|
!(conn->flags & CO_FL_PRIVATE) &&
|
||||||
conn->mux->avail_streams(conn) ==
|
conn->mux->avail_streams(conn) ==
|
||||||
conn->mux->max_streams(conn)) {
|
conn->mux->max_streams(conn)) {
|
||||||
@ -100,6 +102,7 @@ void session_free(struct session *sess)
|
|||||||
|
|
||||||
LIST_ADDQ(&srv->idle_orphan_conns[tid],
|
LIST_ADDQ(&srv->idle_orphan_conns[tid],
|
||||||
&conn->list);
|
&conn->list);
|
||||||
|
srv->curr_idle_conns++;
|
||||||
|
|
||||||
conn->idle_time = now_ms;
|
conn->idle_time = now_ms;
|
||||||
if (!(task_in_wq(srv->idle_task[tid])) &&
|
if (!(task_in_wq(srv->idle_task[tid])) &&
|
||||||
|
Loading…
Reference in New Issue
Block a user