mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-06 03:18:43 +00: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;
|
||||
struct server *srv;
|
||||
|
||||
if (px->map_state & PR_MAP_RECALC)
|
||||
recalc_server_map(px);
|
||||
|
||||
if (px->srv_map_sz == 0)
|
||||
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)
|
||||
{
|
||||
if (px->map_state & PR_MAP_RECALC)
|
||||
recalc_server_map(px);
|
||||
|
||||
if (px->srv_map_sz == 0)
|
||||
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,
|
||||
* 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)
|
||||
{
|
||||
unsigned int h, l;
|
||||
|
||||
if (px->map_state & PR_MAP_RECALC)
|
||||
recalc_server_map(px);
|
||||
|
||||
if (px->srv_map_sz == 0)
|
||||
return NULL;
|
||||
|
||||
@ -133,6 +142,9 @@ static inline struct server *get_server_uh(struct proxy *px, char *uri, int uri_
|
||||
unsigned long hash = 0;
|
||||
int c;
|
||||
|
||||
if (px->map_state & PR_MAP_RECALC)
|
||||
recalc_server_map(px);
|
||||
|
||||
if (px->srv_map_sz == 0)
|
||||
return NULL;
|
||||
|
||||
|
@ -53,6 +53,9 @@
|
||||
#define PR_MODE_HTTP 1
|
||||
#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 */
|
||||
#define PR_CAP_NONE 0x0000
|
||||
#define PR_CAP_FE 0x0001
|
||||
@ -86,6 +89,7 @@ struct proxy {
|
||||
struct list acl; /* ACL declared on this proxy */
|
||||
struct list block_cond; /* early blocking conditions (chained) */
|
||||
struct list switching_rules; /* content switching rules (chained) */
|
||||
int map_state; /* PR_MAP_RECALC */
|
||||
struct server *srv; /* known servers */
|
||||
int srv_act, srv_bck; /* # of running 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 */
|
||||
} else {
|
||||
px->srv_map_sz = 0;
|
||||
px->map_state &= ~PR_MAP_RECALC;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -130,6 +131,7 @@ void recalc_server_map(struct proxy *px)
|
||||
best->wscore -= 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 *));
|
||||
/* recounts servers and their weights */
|
||||
curproxy->map_state = PR_MAP_RECALC;
|
||||
recount_servers(curproxy);
|
||||
recalc_server_map(curproxy);
|
||||
}
|
||||
|
@ -46,7 +46,8 @@
|
||||
|
||||
/* Sets server <s> down, notifies by all available means, recounts the
|
||||
* 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)
|
||||
{
|
||||
@ -58,7 +59,7 @@ static void set_server_down(struct server *s)
|
||||
|
||||
if (s->health == s->rise) {
|
||||
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
|
||||
* a connection. Those which are redispatchable will be queued
|
||||
@ -454,7 +455,7 @@ void process_chk(struct task *t, struct timeval *next)
|
||||
int xferred;
|
||||
|
||||
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
|
||||
* 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:
|
||||
/* print the backend */
|
||||
if (px->cap & PR_CAP_BE) {
|
||||
if (px->map_state & PR_MAP_RECALC)
|
||||
recalc_server_map(px);
|
||||
|
||||
chunk_printf(&msg, sizeof(trash),
|
||||
/* name */
|
||||
"<tr align=center class=\"backend\"><td>Backend</td>"
|
||||
|
Loading…
Reference in New Issue
Block a user