Load balancing in Nginx with redirect rather than proxy

I want to use Nginx in a bit of an unconventional way. I want to load balance between a few servers, but rather than proxy content for those servers I want to redirect to them.

That is, if a request comes into my Nginx server, it should 302 redirect to another server by randomly picking one out of an upstream block or equivalent. I don't even need the other upstream block features, such as weighting (but it wouldn't hurt to have them available if possible).

For now, I have the following config, which does what I need but is a bit ugly:

upstream boxes {
        server 127.0.0.1:46011;
        server 127.0.0.1:46012;
}

server {
        listen 46011;
        return 302 http://box11.example.com$request_uri;
}

server {
        listen 46012;
        return 302 http://box12.example.com$request_uri;
}

server {
        listen 80;
        server_name example.com;

        location / {
                proxy_pass http://boxes;
        }
}

Is there a simpler way to handle this situation without resorting to proxying to myself?


Solution 1:

You can get a random variable from misc module:

set_random $loc_rnd 1 10;

Then choose internal location based on it, with simple weighting:

map $loc_rnd $loc_redirect {
  1 @server1;
  2 @server1;
  ...
  8 @server2;
  9 @server2;
 10 @server2;
}

location / {
 recursive_error_pages on;
 error_page 403 = $loc_redirect;
 return 403;
}

Redirects:

location @server1 {
  internal;
  return 302 http://box11.example.com$request_uri;
}

location @server2 {
  internal;
  return 302 http://box11.example.com$request_uri;
}

Other variant: use return 302 $some_variable; (and full URLs in map) directly in "/" location.