mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-12-16 15:11:01 +01:00
[MEDIUM] improve behaviour with large number of servers per proxy
When a very large number of servers is configured (thousands), shutting down many of them at once could lead to large number of calls to recalc_server_map() which already takes some time. This would result in an O(N^3) computation time, leading to noticeable pauses on slow embedded CPUs on test platforms. Instead, mark the map as dirty and recalc it only when needed.
This commit is contained in:
parent
632f5a7b6f
commit
5af3a694f5
@ -52,6 +52,9 @@ static inline struct server *get_server_rr_with_conns(struct proxy *px)
|
|||||||
int newidx;
|
int newidx;
|
||||||
struct server *srv;
|
struct server *srv;
|
||||||
|
|
||||||
|
if (px->map_state & PR_MAP_RECALC)
|
||||||
|
recalc_server_map(px);
|
||||||
|
|
||||||
if (px->srv_map_sz == 0)
|
if (px->srv_map_sz == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -81,6 +84,9 @@ static inline struct server *get_server_rr_with_conns(struct proxy *px)
|
|||||||
*/
|
*/
|
||||||
static inline struct server *get_server_rr(struct proxy *px)
|
static inline struct server *get_server_rr(struct proxy *px)
|
||||||
{
|
{
|
||||||
|
if (px->map_state & PR_MAP_RECALC)
|
||||||
|
recalc_server_map(px);
|
||||||
|
|
||||||
if (px->srv_map_sz == 0)
|
if (px->srv_map_sz == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -97,11 +103,14 @@ static inline struct server *get_server_rr(struct proxy *px)
|
|||||||
* If any server is found, it will be returned. If no valid server is found,
|
* If any server is found, it will be returned. If no valid server is found,
|
||||||
* NULL is returned.
|
* NULL is returned.
|
||||||
*/
|
*/
|
||||||
static inline struct server *get_server_sh(const struct proxy *px,
|
static inline struct server *get_server_sh(struct proxy *px,
|
||||||
const char *addr, int len)
|
const char *addr, int len)
|
||||||
{
|
{
|
||||||
unsigned int h, l;
|
unsigned int h, l;
|
||||||
|
|
||||||
|
if (px->map_state & PR_MAP_RECALC)
|
||||||
|
recalc_server_map(px);
|
||||||
|
|
||||||
if (px->srv_map_sz == 0)
|
if (px->srv_map_sz == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -133,6 +142,9 @@ static inline struct server *get_server_uh(struct proxy *px, char *uri, int uri_
|
|||||||
unsigned long hash = 0;
|
unsigned long hash = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
if (px->map_state & PR_MAP_RECALC)
|
||||||
|
recalc_server_map(px);
|
||||||
|
|
||||||
if (px->srv_map_sz == 0)
|
if (px->srv_map_sz == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,9 @@
|
|||||||
#define PR_MODE_HTTP 1
|
#define PR_MODE_HTTP 1
|
||||||
#define PR_MODE_HEALTH 2
|
#define PR_MODE_HEALTH 2
|
||||||
|
|
||||||
|
/* values for proxy->map_state */
|
||||||
|
#define PR_MAP_RECALC (1 << 0)
|
||||||
|
|
||||||
/* flag values for proxy->cap. This is a bitmask of capabilities supported by the proxy */
|
/* flag values for proxy->cap. This is a bitmask of capabilities supported by the proxy */
|
||||||
#define PR_CAP_NONE 0x0000
|
#define PR_CAP_NONE 0x0000
|
||||||
#define PR_CAP_FE 0x0001
|
#define PR_CAP_FE 0x0001
|
||||||
@ -86,6 +89,7 @@ struct proxy {
|
|||||||
struct list acl; /* ACL declared on this proxy */
|
struct list acl; /* ACL declared on this proxy */
|
||||||
struct list block_cond; /* early blocking conditions (chained) */
|
struct list block_cond; /* early blocking conditions (chained) */
|
||||||
struct list switching_rules; /* content switching rules (chained) */
|
struct list switching_rules; /* content switching rules (chained) */
|
||||||
|
int map_state; /* PR_MAP_RECALC */
|
||||||
struct server *srv; /* known servers */
|
struct server *srv; /* known servers */
|
||||||
int srv_act, srv_bck; /* # of running servers */
|
int srv_act, srv_bck; /* # of running servers */
|
||||||
int tot_wact, tot_wbck; /* total weights of active and backup servers */
|
int tot_wact, tot_wbck; /* total weights of active and backup servers */
|
||||||
|
|||||||
@ -90,6 +90,7 @@ void recalc_server_map(struct proxy *px)
|
|||||||
tot = 1; /* the first server is enough */
|
tot = 1; /* the first server is enough */
|
||||||
} else {
|
} else {
|
||||||
px->srv_map_sz = 0;
|
px->srv_map_sz = 0;
|
||||||
|
px->map_state &= ~PR_MAP_RECALC;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +131,7 @@ void recalc_server_map(struct proxy *px)
|
|||||||
best->wscore -= tot;
|
best->wscore -= tot;
|
||||||
}
|
}
|
||||||
px->srv_map_sz = tot;
|
px->srv_map_sz = tot;
|
||||||
|
px->map_state &= ~PR_MAP_RECALC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2637,6 +2637,7 @@ int readcfgfile(const char *file)
|
|||||||
|
|
||||||
curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
|
curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
|
||||||
/* recounts servers and their weights */
|
/* recounts servers and their weights */
|
||||||
|
curproxy->map_state = PR_MAP_RECALC;
|
||||||
recount_servers(curproxy);
|
recount_servers(curproxy);
|
||||||
recalc_server_map(curproxy);
|
recalc_server_map(curproxy);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,8 @@
|
|||||||
|
|
||||||
/* Sets server <s> down, notifies by all available means, recounts the
|
/* Sets server <s> down, notifies by all available means, recounts the
|
||||||
* remaining servers on the proxy and transfers queued sessions whenever
|
* remaining servers on the proxy and transfers queued sessions whenever
|
||||||
* possible to other servers.
|
* possible to other servers. It automatically recomputes the number of
|
||||||
|
* servers, but not the map.
|
||||||
*/
|
*/
|
||||||
static void set_server_down(struct server *s)
|
static void set_server_down(struct server *s)
|
||||||
{
|
{
|
||||||
@ -58,7 +59,7 @@ static void set_server_down(struct server *s)
|
|||||||
|
|
||||||
if (s->health == s->rise) {
|
if (s->health == s->rise) {
|
||||||
recount_servers(s->proxy);
|
recount_servers(s->proxy);
|
||||||
recalc_server_map(s->proxy);
|
s->proxy->map_state |= PR_MAP_RECALC;
|
||||||
|
|
||||||
/* we might have sessions queued on this server and waiting for
|
/* we might have sessions queued on this server and waiting for
|
||||||
* a connection. Those which are redispatchable will be queued
|
* a connection. Those which are redispatchable will be queued
|
||||||
@ -454,7 +455,7 @@ void process_chk(struct task *t, struct timeval *next)
|
|||||||
int xferred;
|
int xferred;
|
||||||
|
|
||||||
recount_servers(s->proxy);
|
recount_servers(s->proxy);
|
||||||
recalc_server_map(s->proxy);
|
s->proxy->map_state |= PR_MAP_RECALC;
|
||||||
|
|
||||||
/* check if we can handle some connections queued at the proxy. We
|
/* check if we can handle some connections queued at the proxy. We
|
||||||
* will take as many as we can handle.
|
* will take as many as we can handle.
|
||||||
|
|||||||
@ -3848,6 +3848,9 @@ int produce_content_stats_proxy(struct session *s, struct proxy *px)
|
|||||||
case DATA_ST_PX_BE:
|
case DATA_ST_PX_BE:
|
||||||
/* print the backend */
|
/* print the backend */
|
||||||
if (px->cap & PR_CAP_BE) {
|
if (px->cap & PR_CAP_BE) {
|
||||||
|
if (px->map_state & PR_MAP_RECALC)
|
||||||
|
recalc_server_map(px);
|
||||||
|
|
||||||
chunk_printf(&msg, sizeof(trash),
|
chunk_printf(&msg, sizeof(trash),
|
||||||
/* name */
|
/* name */
|
||||||
"<tr align=center class=\"backend\"><td>Backend</td>"
|
"<tr align=center class=\"backend\"><td>Backend</td>"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user