Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am trying to set up nginx and I don't get the point how to do the following setup:

I have an URL http://somehost.com/foo/bar/123/xxx_xxx that needs to be passed to different backends depending on a range the '123' matches (e.g. 0-150 -> backend1, 151-400 -> backend2, ...).

Since I have almost no experience with regexp, I don't know how to do this (in location?).

Thanks in advance for your help, Sascha

share|improve this question
    
I think you should ask this on Serverfault.com instead. –  Jonas May 12 '11 at 8:25
    
This would be too complicated, unobvious and possible buggy regex. What you're trying to achieve, load-balancing? –  Timofey Stolbov May 12 '11 at 9:06
    
The number would be the resolution of an image. We have 4 different backends to deliver these images and we want load-balancing in the form, that all images with res <150 go to backend1, 151-400 to backend2... –  vreen May 12 '11 at 10:35
add comment

migrated from stackoverflow.com May 14 '11 at 17:02

This question came from our site for professional and enthusiast programmers.

2 Answers

up vote 1 down vote accepted

You can use:

location ~ ^/foo/bar/(\d|\d\d|1[0-4]\d|150)/ {
    proxy_pass backend1;
}

location ~ ^/foo/bar/(15[1-9]|1[6-9]\d|[23]\d\d|400)/ {
    proxy_pass backend2;
}
...

But why you do load balancing in such a heterogeneous way? Why not just shard by image id/hash of name? Your solution will result in different load and even load patterns on different servers. It would be tricky to administer them.

share|improve this answer
    
Thank you, your solutions seems to work great on my testing machine! The reason for this kind of load-balancing is, that some resolutions are requested more often than others and in this way we are able to share the load constantly. However the backends are nodes in a cluster that create the requested resolution on the fly (original image is in an oracle db) and keep them in a cache. In my opinion, this is not the right way, but this was not my decision ;-) However: Thank you very much!! –  Sascha May 16 '11 at 6:24
add comment

If you have a static set of the picture sizes, you can make use of map. Declare backends and a map in http section of Nginx configuration file:

http {
  upstream backend1 {
    server backend1:80;
  }

  upstream backend2 {
    server backend2:80;
  }

  map $pic_size $backend {
    default backend_default;
    80 backend1;
    150 backend2;
  }
}

Declare the location in server:

location ~ ^/foo/bar/(?<pic_size>\d+) {
  proxy_pass http://$backend;
}

If you'd like to support conditional logic, I would recommend using Perl handler. Again, in http:

http {
  perl_set $backend 'sub {
my $r = shift;
my $pic_size = $r->variable("pic_size");

$pic_size <= 150 and return "backend1";
$pic_size <= 400 and return "backend2";
return "backend_default";
}';
}

In location:

location ~ ^/foo/bar/(?<pic_size>\d+) {
  proxy_pass http://$backend:80;
}
share|improve this answer
    
The $map was a huge help to me with a related problem I was trying to figure out (how to selectively forward a particular URL to a backend, though based on a text string rather than numeric) without resorting to use of the dreaded "if". Thanks! –  jsh Jan 17 '13 at 16:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.