[PATCH 2 of 2] Cache: send conditional requests only for cached 200 OK responses
mdounin at mdounin.ru
Tue Nov 25 13:43:44 UTC 2014
On Mon, Nov 24, 2014 at 02:40:41PM -0800, Piotr Sikora wrote:
> Hey Maxim,
> > That's up to a configuration.
> You're right... It seems like a waste of disk space to me, but nginx
> can be forced to do that.
> This still leaves us with only 200 and 206.
The question is: how many other status codes should be considered?
I _think_ that 200 and 206 is good enough list, but I'm not sure.
> > Which problem? You are trying to convince me that that
> > conditional requests shouldn't be used to revalidate responses
> > with non-200 status code because it may not work with some
> > upstream servers. Sure, this can happen. Moreover, it can happen
> > with responses with 200 status code, too.
> No, I'm saying that it cannot work.
> Maybe I shouldn't have tried to explain the reasoning behind
> fd283aa92e04, because it looks that it just added confusion, so let's
> start again.
> 1. client #1 requests "/logo.png" from website behind nginx,
> 2. nginx doesn't have "/logo.png" in cache, so it sends request upstream,
> 3. upstream server rate-limits nginx and replies with 503:
> HTTP/1.1 503 Service Temporarily Unavailable
> Last-Modified: Mon, 24 Nov 2014 22:00:00 GMT
Here is the first problem in the upstream server: it returns an
error with the Last-Modified. This is what nginx avoids for a
> 4. 503 gets force-cached at nginx (due to configuration),
Here you intentionally cache a response which is not
cacheable as per HTTP specification.
> 5. client #2 requests "/logo.png" from website behind nginx,
> 6. nginx has "/logo.png" in cache, but it's expired, so it tries to
> revalidate it:
> GET /logo.png HTTP/1.1
> If-Modified-Since: Mon, 24 Nov 2014 22:00:00 GMT
> 7. upstream replies with 304, accidentally revalidating 503:
> HTTP/1.1 304 Not Modified
> even though, the 304 is generated from:
> HTTP/1.1 200 OK
> Last-Modified: Mon, 10 Nov 2014 00:00:00 GMT
> not from the rate-limiting.
Here is another problem in the upstream server: it returns 304
incorrectly. Strict Last-Modified matching is here for a reason
and, among other benefits, allows to mitigate such problems.
> This scenario describes perfectly behaving upstream server, the only
> issue here is that nginx tries to revalidate response that cannot be
> revalidated and applies 304 Not Modified response to it.
This is not true. The upstream server intentionally does at least
two perfectly stupid things, and additionally you force nginx to
cache an uncacheable response. And all of this combined causes
the problem, not the fact that nginx uses conditional requests.
> > Two trivial solutions include:
> > - fix an upstream server;
> There is no issue with the upstream server, only with nginx
> revalidating non-200 status codes.
This is not true, see above.
> > - disable use of conditional requests, it's off by default.
> So you're saying that just because it's off by default, it's fine for
> it to be broken?
It's not broken. Trying to convince me that it's broken will not
work, for sure. You may have better luck convincing me that the
change will help to mitigate known/seen-in-the-wild problems
without affecting other uses.
More information about the nginx-devel