Nginx proxy_cache: limit parallel requests for the same URL

load balancingnginxreverse-proxy

We're using nginx as a reverse proxy to get files from upstream servers.
The files are not dynamic – at least not on a per request basis – and are (sometimes) behind high latency.

I would like to limit the request for the same URL to exactly 1.

An example of the behaviour I want to avoid:

127.0.0.1 - - [03/Jan/2013:16:08:15 +0100] "GET /part-00132.ts HTTP/1.0" 200 1506068 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:28 +0100] "GET /part-00133.ts HTTP/1.0" 200 1189476 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:29 +0100] "GET /part-00133.ts HTTP/1.0" 200 1189476 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17" "-"
127.0.0.1 - - [03/Jan/2013:16:08:34 +0100] "GET /part-00133.ts HTTP/1.0" 200 1189476 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:44 +0100] "GET /part-00134.ts HTTP/1.0" 200 1762876 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17" "-"
127.0.0.1 - - [03/Jan/2013:16:08:53 +0100] "GET /part-00135.ts HTTP/1.0" 200 1627704 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:59 +0100] "GET /part-00136.ts HTTP/1.0" 200 1252456 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:03 +0100] "GET /part-00134.ts HTTP/1.0" 200 1762876 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:04 +0100] "GET /part-00137.ts HTTP/1.0" 200 1120292 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:07 +0100] "GET /part-00135.ts HTTP/1.0" 200 1627704 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17" "-"
127.0.0.1 - - [03/Jan/2013:16:09:12 +0100] "GET /part-00134.ts HTTP/1.0" 200 1762876 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:14 +0100] "GET /part-00136.ts HTTP/1.0" 200 1252456 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:17 +0100] "GET /part-00135.ts HTTP/1.0" 200 1627704 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:17 +0100] "GET /part-00138.ts HTTP/1.0" 200 1248884 "-" "Prefetch" "-"

It should be like this:

127.0.0.1 - - [03/Jan/2013:16:08:15 +0100] "GET /part-00132.ts HTTP/1.0" 200 1506068 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:28 +0100] "GET /part-00133.ts HTTP/1.0" 200 1189476 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:44 +0100] "GET /part-00134.ts HTTP/1.0" 200 1762876 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17" "-"
127.0.0.1 - - [03/Jan/2013:16:08:53 +0100] "GET /part-00135.ts HTTP/1.0" 200 1627704 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:08:59 +0100] "GET /part-00136.ts HTTP/1.0" 200 1252456 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:04 +0100] "GET /part-00137.ts HTTP/1.0" 200 1120292 "-" "Prefetch" "-"
127.0.0.1 - - [03/Jan/2013:16:09:17 +0100] "GET /part-00138.ts HTTP/1.0" 200 1248884 "-" "Prefetch" "-"

Update:

A diagram to describe the problem a little bit:

            nginx              upstream
           +-----+            +--------+
           |     |            |        |
   A +----->     +-----------------+   |
           |     |            |    |   |
   B +----->     +--------------+  |   |
           |     |            | |  |   |
     <-----+     <--------------|--+   |
           |     |            | |      |
     <-----+     <--------------+      |
           |     |            |        |
   C +----->     +---+        |        |
           |     |   |        |        |
     <-----+     <---+        |        |
           |     |            |        |
           +-----+            +--------+

So I want client B to wait for the A response.

Best Answer

Taken from answer to Nginx how to disable multithread downloads:

Use the nginx example for the limit_conn configuration:

limit_zone one $binary_remote_addr 10m;

server {
  location /download/ {
    limit_conn one 1;
  }
}

It's not just download managers with Range requests that multiplex downloads (and this does not disable Range headers); modern browsers loading pages multiplex requests as well. Be very careful about using this configuration anywhere expect a location that you need to specifically prevent multiplexed downloads for.

Related Topic