mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-29 06:40:59 +01:00
[MEDIUM] listeners: queue proxy-bound listeners at the proxy's
All listeners that are limited by a proxy-specific resource are now queued at the proxy's and not globally. This allows finer-grained wakeups when releasing resource.
This commit is contained in:
parent
08ceb1012b
commit
07687c171e
@ -301,6 +301,7 @@ struct proxy {
|
|||||||
struct pxcounters be_counters; /* backend statistics counters */
|
struct pxcounters be_counters; /* backend statistics counters */
|
||||||
struct pxcounters fe_counters; /* frontend statistics counters */
|
struct pxcounters fe_counters; /* frontend statistics counters */
|
||||||
|
|
||||||
|
struct list listener_queue; /* list of the temporarily limited listeners because of lack of a proxy resource */
|
||||||
struct stktable table; /* table for storing sticking sessions */
|
struct stktable table; /* table for storing sticking sessions */
|
||||||
|
|
||||||
int grace; /* grace time after stop request */
|
int grace; /* grace time after stop request */
|
||||||
|
|||||||
@ -1041,6 +1041,7 @@ static void init_new_proxy(struct proxy *p)
|
|||||||
LIST_INIT(&p->tcp_req.l4_rules);
|
LIST_INIT(&p->tcp_req.l4_rules);
|
||||||
LIST_INIT(&p->req_add);
|
LIST_INIT(&p->req_add);
|
||||||
LIST_INIT(&p->rsp_add);
|
LIST_INIT(&p->rsp_add);
|
||||||
|
LIST_INIT(&p->listener_queue);
|
||||||
|
|
||||||
/* Timeouts are defined as -1 */
|
/* Timeouts are defined as -1 */
|
||||||
proxy_reset_timeouts(p);
|
proxy_reset_timeouts(p);
|
||||||
|
|||||||
@ -499,6 +499,10 @@ void maintain_proxies(int *next)
|
|||||||
goto do_block;
|
goto do_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The proxy is not limited so we can re-enable any waiting listener */
|
||||||
|
if (!LIST_ISEMPTY(&p->listener_queue))
|
||||||
|
dequeue_all_listeners(&p->listener_queue);
|
||||||
|
|
||||||
/* OK we have no reason to block, so let's unblock if we were blocking */
|
/* OK we have no reason to block, so let's unblock if we were blocking */
|
||||||
if (p->state == PR_STIDLE) {
|
if (p->state == PR_STIDLE) {
|
||||||
for (l = p->listen; l != NULL; l = l->next)
|
for (l = p->listen; l != NULL; l = l->next)
|
||||||
|
|||||||
@ -2096,6 +2096,9 @@ struct task *process_session(struct task *t)
|
|||||||
if (!LIST_ISEMPTY(&global_listener_queue))
|
if (!LIST_ISEMPTY(&global_listener_queue))
|
||||||
dequeue_all_listeners(&global_listener_queue);
|
dequeue_all_listeners(&global_listener_queue);
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&s->fe->listener_queue))
|
||||||
|
dequeue_all_listeners(&s->fe->listener_queue);
|
||||||
|
|
||||||
if (unlikely((global.mode & MODE_DEBUG) &&
|
if (unlikely((global.mode & MODE_DEBUG) &&
|
||||||
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
|
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
|
||||||
int len;
|
int len;
|
||||||
|
|||||||
@ -1192,7 +1192,6 @@ int stream_sock_accept(int fd)
|
|||||||
int max_accept = global.tune.maxaccept;
|
int max_accept = global.tune.maxaccept;
|
||||||
int cfd;
|
int cfd;
|
||||||
int ret;
|
int ret;
|
||||||
int loops = 0;
|
|
||||||
|
|
||||||
if (unlikely(l->nbconn >= l->maxconn)) {
|
if (unlikely(l->nbconn >= l->maxconn)) {
|
||||||
listener_full(l);
|
listener_full(l);
|
||||||
@ -1201,15 +1200,31 @@ int stream_sock_accept(int fd)
|
|||||||
|
|
||||||
if (p && p->fe_sps_lim) {
|
if (p && p->fe_sps_lim) {
|
||||||
int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
|
int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
|
||||||
|
|
||||||
|
if (unlikely(!max)) {
|
||||||
|
/* frontend accept rate limit was reached */
|
||||||
|
limit_listener(l, &p->listener_queue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (max_accept > max)
|
if (max_accept > max)
|
||||||
max_accept = max;
|
max_accept = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((!p || p->feconn < p->maxconn) && actconn < global.maxconn && max_accept--) {
|
while (max_accept--) {
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t laddr = sizeof(addr);
|
socklen_t laddr = sizeof(addr);
|
||||||
|
|
||||||
loops++;
|
if (unlikely(actconn >= global.maxconn)) {
|
||||||
|
limit_listener(l, &global_listener_queue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(p && p->feconn >= p->maxconn)) {
|
||||||
|
limit_listener(l, &p->listener_queue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
|
cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
|
||||||
if (unlikely(cfd == -1)) {
|
if (unlikely(cfd == -1)) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
@ -1287,10 +1302,6 @@ int stream_sock_accept(int fd)
|
|||||||
|
|
||||||
} /* end of while (p->feconn < p->maxconn) */
|
} /* end of while (p->feconn < p->maxconn) */
|
||||||
|
|
||||||
/* if we did not even enter the loop, we've reached resource limits */
|
|
||||||
if (!loops && max_accept)
|
|
||||||
limit_listener(l, &global_listener_queue);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user