diff --git a/doc/configuration.txt b/doc/configuration.txt index ed0573165..bfed93698 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -18859,6 +18859,12 @@ hash-key assigned ID values that are evenly distributed over the 32-bit space. + guid The node keys will be derived from the server's guid, when + available, otherwise they will fall back on "id". The benefit + is that it does not depend on ordering at all, only on an + internal stable identifier that can be replicated across many + load balancers. + addr The node keys will be derived from the server's address, when available, or else fall back on "id". diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index bbc548081..a3dbc606a 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -251,6 +251,7 @@ struct pid_list { enum srv_hash_key { SRV_HASH_KEY_ID = 0, /* derived from server puid, 28 LSB used */ SRV_HASH_KEY_ID32, /* derived from server puid, 32 bits used */ + SRV_HASH_KEY_GUID, /* derived from server guid */ SRV_HASH_KEY_ADDR, /* derived from server address */ SRV_HASH_KEY_ADDR_PORT /* derived from server address and port */ }; diff --git a/src/lb_chash.c b/src/lb_chash.c index cf34370bf..ce60bee8b 100644 --- a/src/lb_chash.c +++ b/src/lb_chash.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,7 @@ static inline u32 chash_compute_server_key(struct server *s) { enum srv_hash_key hash_key = s->hash_key; struct server_inetaddr srv_addr; + const char *guid_key = NULL; u32 key; /* If hash-key is addr or addr-port then we need the address, but if we @@ -96,6 +98,11 @@ static inline u32 chash_compute_server_key(struct server *s) } break; + case SRV_HASH_KEY_GUID: + guid_key = guid_get(&s->guid); + if (!guid_key) + hash_key = SRV_HASH_KEY_ID; + break; default: break; } @@ -121,6 +128,10 @@ static inline u32 chash_compute_server_key(struct server *s) } break; + case SRV_HASH_KEY_GUID: + key = XXH32(guid_key, strlen(guid_key), 0); + break; + case SRV_HASH_KEY_ID32: key = full_hash(htonl(s->puid)); break; diff --git a/src/server.c b/src/server.c index 4594e1a11..9ebce0c8c 100644 --- a/src/server.c +++ b/src/server.c @@ -1015,7 +1015,7 @@ static int srv_parse_hash_key(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err) { if (!args[*cur_arg + 1]) { - memprintf(err, "'%s expects 'id', 'id32', 'addr', or 'addr-port' value", args[*cur_arg]); + memprintf(err, "'%s expects 'id', 'id32', 'guid', 'addr', or 'addr-port' value", args[*cur_arg]); return ERR_ALERT | ERR_FATAL; } @@ -1025,6 +1025,9 @@ static int srv_parse_hash_key(char **args, int *cur_arg, else if (strcmp(args[*cur_arg + 1], "id32") == 0) { newsrv->hash_key = SRV_HASH_KEY_ID32; } + else if (strcmp(args[*cur_arg + 1], "guid") == 0) { + newsrv->hash_key = SRV_HASH_KEY_GUID; + } else if (strcmp(args[*cur_arg + 1], "addr") == 0) { newsrv->hash_key = SRV_HASH_KEY_ADDR; } @@ -1032,7 +1035,7 @@ static int srv_parse_hash_key(char **args, int *cur_arg, newsrv->hash_key = SRV_HASH_KEY_ADDR_PORT; } else { - memprintf(err, "'%s' has to be 'id', 'id32', 'addr', or 'addr-port'", args[*cur_arg]); + memprintf(err, "'%s' has to be 'id', 'id32', 'guid', 'addr', or 'addr-port'", args[*cur_arg]); return ERR_ALERT | ERR_FATAL; }