Opened 5 years ago

Closed 5 years ago

#1862 closed defect (duplicate)

Cache-Control:no-store should remove entry from cache (with proxy_cache_background_update+proxy_cache_use_stale)

Reported by: Ondřej Nový Owned by:
Priority: minor Milestone:
Component: other Version: 1.16.x
Keywords: Cc:
uname -a: Linux mustafar 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.16.1
built with OpenSSL 1.1.1c 28 May 2019
TLS SNI support enabled
configure arguments: --with-debug --with-cc-opt='-g -O2 -fdebug-prefix-map=/builds/nginx/szn-nginx=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2 -I /builds/nginx/szn-nginx/openssl/.openssl/include -pthread -DNGX_HAVE_CLOCK_MONOTONIC=0' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC -L /builds/nginx/szn-nginx/openssl/.openssl/lib -pthread' --prefix=/www/nginx --conf-path=/www/nginx/doc/nginx.conf --http-log-path=/www/nginx/log/access.log --error-log-path=/www/nginx/log/error.log --lock-path=/www/nginx/lock/nginx.lock --pid-path=/var/run/nginx.pid --modules-path=/www/nginx/modules --http-client-body-temp-path=/www/nginx/var/lib/body --http-fastcgi-temp-path=/www/nginx/var/lib/fastcgi --http-proxy-temp-path=/www/nginx/var/lib/proxy --http-scgi-temp-path=/www/nginx/var/lib/scgi --http-uwsgi-temp-path=/www/nginx/var/lib/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_geoip_module=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module

Description

We are using proxy_cache_background_update+proxy_cache_use_stale.

We have backend which sometimes sets Cache-Control to max-age>10, but for same request sometimes to no-cache/no-store. When we cache entry with max-age=10, that entry keeps in cache forever, even if we set no-cache/no-store in late request.

Example nginx conf to simulate same situation:

events {
    use epoll;
}

http {
    proxy_cache_path /home/debian/test-cache/cache levels=1:2 keys_zone=cache:10m inactive=10m max_size=256m;

    server {
        listen  8080;

        location /in/cache {
            return 200;
            add_header "Cache-Control" "max-age=10" always;
        }

        location /in/no-cache {
            return 200;
            add_header "Cache-Control" "no-store" always;
        }

        location / {
            add_header "X-Cache-Status" $upstream_cache_status always;
            proxy_cache cache;
            proxy_cache_key "same";
            proxy_cache_lock on;
            proxy_cache_background_update on;
            proxy_cache_use_stale updating error timeout;
            proxy_cache_valid any 10s;
            proxy_pass http://localhost:8080/in/;
        }
    }
}


proxy_cache_key is intentionally same in this example config for all location, because i want to test same cache entry.

Add entry into cache:

root@mustafar:/home/debian/test-cache# wget -S localhost:8080/cache -O /dev/null 2>&1 | grep X-Cache-Status
  X-Cache-Status: MISS
root@mustafar:/home/debian/test-cache# wget -S localhost:8080/cache -O /dev/null 2>&1 | grep X-Cache-Status
  X-Cache-Status: HIT
root@mustafar:/home/debian/test-cache# wget -S localhost:8080/no-cache -O /dev/null 2>&1 | grep X-Cache-Status
  X-Cache-Status: HIT

After >10s, entry is not valid, it's STALEd:

root@mustafar:/home/debian/test-cache# wget -S localhost:8080/no-cache -O /dev/null 2>&1 | grep X-Cache-Status
  X-Cache-Status: STALE

which is correct. Background task to refresh cache has been started now, because proxy_cache_background_update is on. /in/no-cache location returns Cache-Control: no-store, which should refresh cache entry (in this situation: remove it). But cache entry remains here for ever (until inactive=10m is hit).

Change History (1)

comment:1 by Maxim Dounin, 5 years ago

Resolution: duplicate
Status: newclosed

Removing a cache entry if an update request returns a non-cacheable response isn't always a good idea: notably, the response might be an uncacheable error, and throwing away cached item in such a case is a bad idea. A readily available solution would be to use 'Cache-Control: stale-while-revalidate=<timeout>" instead of "proxy_cache_use_stale updating" - this allows to specify a timeout to stop using cached response if we weren't able to update it.

Closing this as a duplicate of #853, which is about the same problem and also links to the relevant thread in the nginx-devel@ mailing list.

Note: See TracTickets for help on using tickets.