Mark stale cache content as "invalid" on non-cacheable responses
mdounin at mdounin.ru
Tue Nov 17 18:25:00 UTC 2015
On Tue, Nov 17, 2015 at 05:25:30PM +0000, Mindaugas Rasiukevicius wrote:
> Context: consider nginx used as a cache with proxy_cache_use_stale set
> to 'http_500' and the 'updating' parameter set i.e. it caches errors and
> serves the stale content while updating. Suppose the upstream temporarily
> responds with HTTP 504 and Cache-Control being max-age=3. The error gets
> cached, but after 3 seconds it expires. At this point, let's say the
> upstream server starts serving HTTP 200 responses, but with Cache-Control
> set to 'no-cache'.
> The cache manager will not LRU the expired content immediately; it will
> stay in the EXPIRED state while subsequent requests will result in 200s.
> Problem: if there are multiple processes racing, the ones in the UPDATING
> state will serve stale 504s. That results in sporadic errors, e.g.:
> 200 EXPIRED
> 504 UPDATING
> 200 EXPIRED
> At the very least, I think the stale cache content should be marked as
> "invalid" after the no-cache response (with the possibility to become
> valid again if it becomes cacheable). Whether the object should be kept
> at all is something to debate.
> Please find the preliminary patch attached.
I don't see how a response with "no-cache" is no different from an
earlier error. Consider slightly different scenario:
- a response is cached and then expires,
- an attempt to fetch new response results in a non-cacheable
In such a case, removing previously cached response is the worst
thing we can possibly do. We are expected to return previously
cached stale responses in all cases we are configured to do so.
The change you've proposed completely rules out possibility of
correct handling of this scenario.
Trivial solutions to the problem you've described would be to
disable use of stale responses completely (which is the default),
or use "proxy_cache_use_stale http_504", or to avoid caching of
504 errors (and the later is something RFC suggests to do by
default with any errors).
And while I agree that it would be good to behave better in the
scenario you've described, I tend to disagree with the change
suggested, and I'm not even sure a good solution exists.
More information about the nginx-devel