MEDIUM: backend: add the "http-reuse aggressive" strategy
This strategy is less extreme than "always", it only dispatches first requests to validated reused connections, and moves a connection from the idle list to the safe list once it has seen a second request, thus proving that it could be reused.
This commit is contained in:
parent
7017cb040c
commit
449d74a906
@ -1046,17 +1046,43 @@ int connect_server(struct stream *s)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS ||
|
/* Below we pick connections from the safe or idle lists based
|
||||||
((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_SAFE && s->txn && (s->txn->flags & TX_NOT_FIRST)))
|
* on the strategy, the fact that this is a first or second
|
||||||
&& !LIST_ISEMPTY(&srv->idle_conns)) {
|
* (retryable) request, with the indicated priority (1 or 2) :
|
||||||
/* We're going to have to pick the first connection
|
*
|
||||||
* from this pool and use it for our purposes. We may
|
* SAFE AGGR ALWS
|
||||||
* have to get rid of the current idle connection, so
|
*
|
||||||
* for this we try to swap it with the other owner's.
|
* +-----+-----+ +-----+-----+ +-----+-----+
|
||||||
* That way it may remain alive for others to pick.
|
* req| 1st | 2nd | req| 1st | 2nd | req| 1st | 2nd |
|
||||||
*/
|
* ----+-----+-----+ ----+-----+-----+ ----+-----+-----+
|
||||||
srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
|
* safe| - | 2 | safe| 1 | 2 | safe| 1 | 2 |
|
||||||
|
* ----+-----+-----+ ----+-----+-----+ ----+-----+-----+
|
||||||
|
* idle| - | 1 | idle| - | 1 | idle| 2 | 1 |
|
||||||
|
* ----+-----+-----+ ----+-----+-----+ ----+-----+-----+
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&srv->idle_conns) &&
|
||||||
|
((s->be->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR &&
|
||||||
|
s->txn && (s->txn->flags & TX_NOT_FIRST))) {
|
||||||
|
srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
|
||||||
|
}
|
||||||
|
else if (!LIST_ISEMPTY(&srv->safe_conns) &&
|
||||||
|
((s->txn && (s->txn->flags & TX_NOT_FIRST)) ||
|
||||||
|
(s->be->options & PR_O_REUSE_MASK) >= PR_O_REUSE_AGGR)) {
|
||||||
|
srv_conn = LIST_ELEM(srv->safe_conns.n, struct connection *, list);
|
||||||
|
}
|
||||||
|
else if (!LIST_ISEMPTY(&srv->idle_conns) &&
|
||||||
|
(s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS) {
|
||||||
|
srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we've picked a connection from the pool, we now have to
|
||||||
|
* detach it. We may have to get rid of the previous idle
|
||||||
|
* connection we had, so for this we try to swap it with the
|
||||||
|
* other owner's. That way it may remain alive for others to
|
||||||
|
* pick.
|
||||||
|
*/
|
||||||
|
if (srv_conn) {
|
||||||
LIST_DEL(&srv_conn->list);
|
LIST_DEL(&srv_conn->list);
|
||||||
LIST_INIT(&srv_conn->list);
|
LIST_INIT(&srv_conn->list);
|
||||||
|
|
||||||
@ -1069,8 +1095,8 @@ int connect_server(struct stream *s)
|
|||||||
reuse = 1;
|
reuse = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we may have to release our connection if we couldn't swap it */
|
||||||
if (old_conn && !old_conn->owner) {
|
if (old_conn && !old_conn->owner) {
|
||||||
/* we couldn't swap our connection, let's release it */
|
|
||||||
LIST_DEL(&old_conn->list);
|
LIST_DEL(&old_conn->list);
|
||||||
conn_force_close(old_conn);
|
conn_force_close(old_conn);
|
||||||
conn_free(old_conn);
|
conn_free(old_conn);
|
||||||
|
@ -5042,6 +5042,12 @@ stats_error_parsing:
|
|||||||
if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
|
if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(args[1], "aggressive") == 0) {
|
||||||
|
curproxy->options &= ~PR_O_REUSE_MASK;
|
||||||
|
curproxy->options |= PR_O_REUSE_AGGR;
|
||||||
|
if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
else if (strcmp(args[1], "always") == 0) {
|
else if (strcmp(args[1], "always") == 0) {
|
||||||
/* enable a graceful server shutdown on an HTTP 404 response */
|
/* enable a graceful server shutdown on an HTTP 404 response */
|
||||||
curproxy->options &= ~PR_O_REUSE_MASK;
|
curproxy->options &= ~PR_O_REUSE_MASK;
|
||||||
@ -5050,7 +5056,7 @@ stats_error_parsing:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'always'.\n", file, linenum, args[0]);
|
Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -5032,6 +5032,7 @@ void http_end_txn_clean_session(struct stream *s)
|
|||||||
struct proxy *fe = strm_fe(s);
|
struct proxy *fe = strm_fe(s);
|
||||||
struct connection *srv_conn;
|
struct connection *srv_conn;
|
||||||
struct server *srv;
|
struct server *srv;
|
||||||
|
unsigned int prev_flags = s->txn->flags;
|
||||||
|
|
||||||
/* FIXME: We need a more portable way of releasing a backend's and a
|
/* FIXME: We need a more portable way of releasing a backend's and a
|
||||||
* server's connections. We need a safer way to reinitialize buffer
|
* server's connections. We need a safer way to reinitialize buffer
|
||||||
@ -5194,6 +5195,12 @@ void http_end_txn_clean_session(struct stream *s)
|
|||||||
else if ((srv_conn->flags & CO_FL_PRIVATE) ||
|
else if ((srv_conn->flags & CO_FL_PRIVATE) ||
|
||||||
((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR))
|
((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR))
|
||||||
si_idle_conn(&s->si[1], &srv->priv_conns);
|
si_idle_conn(&s->si[1], &srv->priv_conns);
|
||||||
|
else if (prev_flags & TX_NOT_FIRST)
|
||||||
|
/* note: we check the request, not the connection, but
|
||||||
|
* this is valid for strategies SAFE and AGGR, and in
|
||||||
|
* case of ALWS, we don't care anyway.
|
||||||
|
*/
|
||||||
|
si_idle_conn(&s->si[1], &srv->safe_conns);
|
||||||
else
|
else
|
||||||
si_idle_conn(&s->si[1], &srv->idle_conns);
|
si_idle_conn(&s->si[1], &srv->idle_conns);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user