0

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?

mmuurr
  • 125
  • 5

1 Answers1

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.

anx
  • 6,875
  • 4
  • 22
  • 45
  • Thanks! I didn't think about that `map` functionality. Re: the use, in my case the cookie won't be set by any of the upstream servers; rather, it's set by a _downstream_ process, i.e. before any request ever makes it to the upstreams. Identical results (across different clients) from that earlier process should be routed to the same upstream, hence the need for this little trick. Anyhow, thanks again! – mmuurr Oct 18 '20 at 00:08