proxy_cache_min_uses not counted per variant on initial requests
|Reported by:||Owned by:|
|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 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
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.
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
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
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
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.