Opened 4 years ago

#1990 new defect

proxy_cache_min_uses not counted per variant on initial requests

Reported by: chrisd8088@… Owned by:
Priority: minor Milestone:
Component: documentation Version: 1.16.x
Keywords: Cc:
uname -a: Linux 10-0-1-120 4.19.0-0.bpo.6-amd64 #1 SMP Debian 4.19.67-2+deb10u2~bpo9+1 (2019-11-12) x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.16.0
built with OpenSSL 1.1.0k 28 May 2019 (running with OpenSSL 1.1.0l 10 Sep 2019)
TLS SNI support enabled
configure arguments: --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --with-debug --with-http_auth_request_module --with-http_sub_module --with-ipv6 --prefix=/usr --user=www-data --group=www-data --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-client-body-temp-path=/var/lib/nginx/body

Description

When proxy_cache_min_uses is set to a value greater than 1, and multiple requests arrive which all resolve to a common primary proxy_cache_key but which are different variants according to the Vary response header, the requests are not counted on a per-variant basis at first, until at least one variant is cached.

Suppose proxy_cache_min_uses 2 is configured and two requests for the same URL arrive with different Accept-Encoding headers, and suppose the backend responds to both with Vary: Accept-Encoding.

The second request will be cached in this case, even though only one "use" has so far been seen for that variant.

After this, future requests will be counted on a per-variant basis, however.

Consider the following sequence of requests for the same URL with proxy_cache_min_uses 2:

Accept-Encoding: foo                MISS (not cached)
Accept-Encoding: bar                MISS (cached)
Accept-Encoding: bar                HIT

Accept-Encoding: foo                MISS (not cached)
Accept-Encoding: abc                MISS (not cached)
Accept-Encoding: foo                MISS (cached)
Accept-Encoding: abc                MISS (cached)
Accept-Encoding: foo                HIT
Accept-Encoding: abc                HIT

So the foo variant ends up not cached until its third request, while the bar variant is cached on its first request. Only the abc variant is correctly cached on its second request.

This appears to be due to the way that ngx_http_file_cache_open() first calls ngx_http_file_cache_exists() but only proceeds to ngx_http_file_cache_read() if a "primary" cache file is found, and it's only in ngx_http_file_cache_read() that the variant is tested and a "secondary" cache file may be opened instead using ngx_http_file_cache_reopen() (see https://hg.nginx.org/nginx/file/stable-1.16/src/http/ngx_http_file_cache.c#l598).

So "uses" are counted generically against the primary key, regardless of variation, until a first cache file is created for that key.

It would be ideal if, instead, per-variant use counting could be done from the start for each unique cache key.

Change History (0)

Note: See TracTickets for help on using tickets.