NGINX load balancing hash: use cookie value if present, ip_hash if not
I'm trying to figure out how to do some if-else logic in NGINX's upstream
load-balancing directive. Basically, I'd like to use the method:
hash $cookie_my_cookie_name consistent;
... if the cookie (my_cookie_name
) is present. If that cookie is not present, then I'd like the upstream selection method to fall-back to the built-in:
ip_hash;
I haven't been able to find examples anywhere in NGINX's docs on how to 'try' one upstream selection method and if that can't work select an alternative method.
The scenario I'm a but worried about is if the cookie isn't present, the $cookie_my_cookie_name
variable interpolates (at least in the logs) to -
, which is a string, but will always hash to the same upstream server, which is exactly what I don't want. (Thus the test needs to be for the absence of the cookie, which, if present, will always hold a 'good' value.)
Any ideas?
Solution 1:
You should be able to transform your hash key using one or more map
blocks.
Not tested:
map $cookie_my_cookie_name $my_hash_key
{
"" $remote_addr;
default $cookie_my_cookie_name;
}
upstream {
hash $my_hash_key consistent;
}
I do not think what you describe in your question really serves most purposes well, though. As soon as the cookie is set, the upstream is likely changes - which may mean a user gets transferred to an upstream that does not have his history cached as soon as the cookie is set.
Instead, consider mapping the the hash key to something like a reasonably sized prefix of the IPv4/IPv6 address, and defaulting to the same mechanism for the cookie, so the default case and the upstream assigned based on the cookie resolves to the same value, initially.