# Proxy\_cache\_lock allow multiple requests to remote server in some cases

**URL:** <https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963>\
**Category:** NGINX\
**Created:** [January 29, 2016, 1:13am UTC](https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963 "2016-01-29T01:13:41Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sadaf\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@Sadaf\_N](https://www.ruby-forum.com/u/Sadaf_N)\
**Post date:** [January 29, 2016, 1:13am UTC](https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963/1 "2016-01-29T01:13:41Z")

</div>

My understanding of proxy\_cache\_lock is that only one request should be  
passed to the proxied server for a given uri, even if many requests from  
the  
same uri/key are hitting nginx while it is being refreshed.

When the cache folder specified in the proxy\_cache\_path is empty, it  
works  
well and behave like I described above.  
However, if the element in the cache already exists, but is expired  
(according to proxy\_cache\_valid configuration), all concurrent requests  
will  
hit the proxied server and the resource will be downloaded multiple  
times.

Here is my config:

proxy\_cache\_path /usr/share/nginx/cache levels=1:2 keys\_zone=CACHE:10m  
max\_size=2g inactive=1440m;

server {  
listen 80 default\_server;  
listen [::]:80 default\_server ipv6only=on;

```
    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name localhost;

    location /videos {

            proxy_cache CACHE;
            proxy_cache_valid 200 15s;
            proxy_cache_revalidate on;
            proxy_cache_lock on;
            proxy_cache_lock_timeout 30s;
            proxy_cache_lock_age 30s;
            proxy_cache_use_stale error timeout invalid_header
                                   http_500 http_502 http_503 

```

http\_504;

```
            proxy_pass http://origin_server/videos;
    }

```

}

Basically what I want to do is to be able to take advantage of the  
“proxy\_cache\_revalidate on” to force a If-Modified-Since request, but  
only  
one request should go and fetch the new element from the proxied server,  
even if multiple requests are coming in for the same uri/key and the  
cache  
is expired.

To be more specific, in my case, the resources downloaded are videos  
between  
1MB to 10MB in size, so they take some time to download and saving  
bandwidth  
is important, and only one request should be done, not multiple (to the  
proxied server).

Using “proxy\_cache\_use\_stale updating” is also not an option since I  
want  
all requests that are coming simultaneously to wait and use the new  
resource  
when there is a new one returned from the proxied server.

Is there something I am doing wrong, or is this the expected behavior?  
Is  
there a way to do what I am trying to do with nginx?

I am using nginx 1.8.1 on Ubuntu Server 14.04 x64.

Regards,  
Jeeeff

Posted at Nginx Forum:

> **[proxy\_cache\_lock allow multiple requests to remote server in some cases](https://forum.nginx.org/read.php?2,264203,264203#msg-264203)**
>
> My understanding of proxy\_cache\_lock is that only one request should be passed to the proxied server for a given uri, even if many requests from the same uri/key are hitting nginx while it is being refreshed. When the cache folder specified in the...

---

<div class="post-metadata">

**Author:** ![jeeeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c6cbf5/32.png) [@jeeeff](https://www.ruby-forum.com/u/jeeeff)\
**Post date:** [February 5, 2016, 5:02pm UTC](https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963/2 "2016-02-05T17:02:59Z")

</div>

Anyone else noticed the same behavior?

I wasn’t sure if that kind of behavior was correct, but as I said the  
lock  
works properly and only one request get forwarded to the backend server  
when  
there is no cached item in the cache (that is: the cache is empty), so  
to me  
the behavior should be the same when the cache is being refreshed (I  
don’t  
see why it would be different?), but that is not the case… so it looks  
like a defect to me.

I also tried to confirm if other cache software do the same thing, such  
as  
varnish, and in theory they have this “waiting queue” which should  
guarantee  
that only one request gets forwarded, but there is a bug right now which  
actually makes the thing even worst than Nginx (at least Nginx sends a  
If-Modified-Since, but varnish just do a full request for all concurrent  
requests, their bug tracking ticket is  
[Varnish HTTP Cache — Varnish HTTP Cache](https://www.varnish-cache.org/trac/ticket/1799)). The workaround  
mentioned  
does no even provide the same behavior (it hits the old cache instead of  
waiting the queued request), so does not work for me.

Sorry for mentioning about a third party product such as varnish on this  
forum, but since I wasn’t receiving any response, I wanted to see if  
other  
solutions had this functionality (and confirm my post made sense…),  
but  
then I am now back with Nginx as it works better (and is easier to use)  
anyway, at least until the bug is resolved on varnish. If this issue is  
resolved on nginx, that would be even better for me… nginx is more  
flexible and easier to use.

Posted at Nginx Forum:

> **[Re: proxy\_cache\_lock allow multiple requests to remote server in some cases](https://forum.nginx.org/read.php?2,264203,264383#msg-264383)**
>
> My understanding of proxy\_cache\_lock is that only one request should be passed to the proxied server for a given uri, even if many requests from the same uri/key are hitting nginx while it is being refreshed. When the cache folder specified in the...

---

<div class="post-metadata">

**Author:** ![jeeeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c6cbf5/32.png) [@jeeeff](https://www.ruby-forum.com/u/jeeeff)\
**Post date:** [January 29, 2016, 2:48pm UTC](https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963/3 "2016-01-29T14:48:02Z")

</div>

Hello!

On Thu, Jan 28, 2016 at 07:13:11PM -0500, jeeeff wrote:

> My understanding of proxy\_cache\_lock is that only one request should be  
> passed to the proxied server for a given uri, even if many requests from the  
> same uri/key are hitting nginx while it is being refreshed.
> 
> When the cache folder specified in the proxy\_cache\_path is empty, it works  
> well and behave like I described above.  
> However, if the element in the cache already exists, but is expired  
> (according to proxy\_cache\_valid configuration), all concurrent requests will  
> hit the proxied server and the resource will be downloaded multiple times.

That’s expected, see [Alphabetical index of directives](http://nginx.org/r/proxy_cache_lock:)

: When enabled, only one request at a time will be allowed to  
: populate a new cache element identified according to the  
: proxy\_cache\_key directive by passing a request to a proxied  
: server.

Note “a new cache element”. It does not work while updating cache  
elements, this is not implemented.

[…]

> Using “proxy\_cache\_use\_stale updating” is also not an option since I want  
> all requests that are coming simultaneously to wait and use the new resource  
> when there is a new one returned from the proxied server.
> 
> Is there something I am doing wrong, or is this the expected behavior? Is  
> there a way to do what I am trying to do with nginx?

See above, this is expected behaviour - as of now proxy\_cache\_lock  
does nothing while updating cache elements. Using  
“proxy\_cache\_use\_stale updating” is recommended if you need to  
reduce concurrency while updating cache elements.

If “proxy\_cache\_use\_stale updating” doesn’t work for you, you may  
try extending “proxy\_cache\_lock” to also cover updating. Current  
implementation doesn’t try to do this to reduce complexity.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![jeeeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c6cbf5/32.png) [@jeeeff](https://www.ruby-forum.com/u/jeeeff)\
**Post date:** [February 5, 2016, 5:47pm UTC](https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963/4 "2016-02-05T17:47:24Z")

</div>

Hello!

On Fri, Feb 05, 2016 at 11:02:31AM -0500, jeeeff wrote:

> Anyone else noticed the same behavior?
> 
> I wasn’t sure if that kind of behavior was correct, but as I said the lock  
> works properly and only one request get forwarded to the backend server when  
> there is no cached item in the cache (that is: the cache is empty), so to me  
> the behavior should be the same when the cache is being refreshed (I don’t  
> see why it would be different?), but that is not the case… so it looks  
> like a defect to me.

[…]

You can find the detailed response to your original message here:

> **[proxy\_cache\_lock allow multiple requests to remote server in some cases](http://mailman.nginx.org/pipermail/nginx/2016-January/049734.html)**

Unfortunately, forum interface is broken and is unable to show it  
in the correct thread. Consider using the mailing list directly  
instead, see [http://nginx.org/en/support.html](http://nginx.org/en/support.html).

Additionally, it’s also unlikely that you’ll see this message as  
well, due to the same forum bug.

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![jeeeff](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/c6cbf5/32.png) [@jeeeff](https://www.ruby-forum.com/u/jeeeff)\
**Post date:** [February 5, 2016, 6:33pm UTC](https://www.ruby-forum.com/t/proxy-cache-lock-allow-multiple-requests-to-remote-server-in-some-cases/243963/5 "2016-02-05T18:33:33Z")

</div>

## Maxim D. Wrote:

> Additionally, it’s also unlikely that you’ll see this message as  
> well, due to the same forum bug.
> 
> –  
> Maxim D.  
> [http://nginx.org/](http://nginx.org/)

Thanks a lot for the info!  
Yes, after I re-read the documentation, I kind of understood that  
“populate  
a new element” could have been interpreted the wrong way.  
Anyway, now I know for sure what the implemented behavior is, and that I  
am  
not making a mistake or missing some configuration.

And as you suggested, I also thought of looking at the code to see if  
that  
could be fixed/implemented, that is, if I get some time to get into the  
project source code…

Jeeeff

Posted at Nginx Forum:  
[https://forum.nginx.org/read.php?2,264203,264386#msg-264386](https://forum.nginx.org/read.php?2,264203,264386#msg-264386)
