For ordinary requests, we (try to) replace stale cache objects when we fetch new ones:
- in
HSH_Lookup(), we return the "best object" via the ocp argument
- in
cnt_lookup(), we either pass this object directly to VBF_Fetch() as the oldoc argument for a bgfetch, or indirectly by saving it in req->stale_oc for the miss case.
- in
vbf_stp_fetchend(), when we have a new cache object, we kill a single stale object which was saved before, if any
Now this mechanism clearly does not work with hash_always_miss, as previously documented in #2945 : If this mode is present, we insert a new object, never cleaning up old stale objects (because we do not track them).
A different but seemingly similar issue exists with hash_ignore_busy: For concurrent requests, we insert multiple objects, but only remove one.
This ticket is to question if this behavior is in fact what we want. I see the following issues:
- For the short ttl + long grace case, we can end up with a relevant number of unused cache objects
- This behavior quite likely is un-POLA
- Removing the surplus objects requires a PURGE or a BAN
On the other end, I could imagine cases where these facilities are used to deliberately create fallback objects in cache, and I wonder if such use cases relying on the property of inserting additional objects exist.
Demo
vcl:
vcl 4.1;
import vtc;
backend alwaysdown none;
sub vcl_recv {
if (req.url == "/ham") {
set req.hash_always_miss = true;
} else if (req.url == "/hib") {
set req.hash_ignore_busy = true;
}
set req.url = "/";
return (hash);
}
sub vcl_backend_error {
vtc.sleep(10s);
set beresp.status = 200;
set beresp.ttl = 1s;
set beresp.grace = 1h;
synthetic("");
return (deliver);
}
slink@haggis21:~$ /tmp/bin/varnishstat -1 -f MAIN.n_object -f MAIN.n_objectcore
MAIN.n_object 7 . object structs made
MAIN.n_objectcore 7 . objectcore structs made
slink@haggis21:~$ curl -I localhost:8080/ham &curl -I localhost:8080/ham &
[1] 27050
[2] 27051
slink@haggis21:~$ /tmp/bin/varnishstat -1 -f MAIN.n_object -f MAIN.n_objectcore
MAIN.n_object 7 . object structs made
MAIN.n_objectcore 7 . objectcore structs made
slink@haggis21:~$ # waHTTP/1.1 200 OK
HTTP/1.1 200 OK
Date: Tue, 17 Aug 2021 13:15:22 GMT
Date: Tue, 17 Aug 2021 13:15:22 GMT
Server: Varnish
Server: Varnish
X-Varnish: 131080
X-Varnish: 65547
Age: 10
Age: 10
Via: 1.1 varnish (Varnish/6.6)
Via: 1.1 varnish (Varnish/6.6)
Accept-Ranges: bytes
Accept-Ranges: bytes
Content-Length: 0
Content-Length: 0
Connection: keep-alive
Connection: keep-alive
[1]- Done curl -I localhost:8080/ham
[2]+ Done curl -I localhost:8080/ham
slink@haggis21:~$ /tmp/bin/varnishstat -1 -f MAIN.n_object -f MAIN.n_objectcore
MAIN.n_object 9 . object structs made
MAIN.n_objectcore 9 . objectcore structs made
slink@haggis21:~$ /tmp/bin/varnishstat -1 -f MAIN.n_object -f MAIN.n_objectcore
MAIN.n_object 9 . object structs made
MAIN.n_objectcore 9 . objectcore structs made
slink@haggis21:~$ curl -I localhost:8080/hib &curl -I localhost:8080/hib &
[1] 27158
[2] 27159
slink@haggis21:~$ HTTP/1.1 200 OK
HTTP/1.1 200 OK
Date: Tue, 17 Aug 2021 13:15:22 GMT
Date: Tue, 17 Aug 2021 13:15:22 GMT
Server: Varnish
Server: Varnish
X-Varnish: 65550 131081
X-Varnish: 131083 131081
Age: 58
Age: 58
Via: 1.1 varnish (Varnish/6.6)
Via: 1.1 varnish (Varnish/6.6)
Accept-Ranges: bytes
Accept-Ranges: bytes
Content-Length: 0
Content-Length: 0
Connection: keep-alive
Connection: keep-alive
[1]- Done curl -I localhost:8080/hib
[2]+ Done curl -I localhost:8080/hib
slink@haggis21:~$ /tmp/bin/varnishstat -1 -f MAIN.n_object -f MAIN.n_objectcore
MAIN.n_object 9 . object structs made
MAIN.n_objectcore 11 . objectcore structs made
slink@haggis21:~$ /tmp/bin/varnishstat -1 -f MAIN.n_object -f MAIN.n_objectcore
MAIN.n_object 10 . object structs made
MAIN.n_objectcore 10 . objectcore structs made
For ordinary requests, we (try to) replace stale cache objects when we fetch new ones:
HSH_Lookup(), we return the "best object" via theocpargumentcnt_lookup(), we either pass this object directly toVBF_Fetch()as theoldocargument for a bgfetch, or indirectly by saving it inreq->stale_ocfor themisscase.vbf_stp_fetchend(), when we have a new cache object, we kill a single stale object which was saved before, if anyNow this mechanism clearly does not work with
hash_always_miss, as previously documented in #2945 : If this mode is present, we insert a new object, never cleaning up old stale objects (because we do not track them).A different but seemingly similar issue exists with
hash_ignore_busy: For concurrent requests, we insert multiple objects, but only remove one.This ticket is to question if this behavior is in fact what we want. I see the following issues:
On the other end, I could imagine cases where these facilities are used to deliberately create fallback objects in cache, and I wonder if such use cases relying on the property of inserting additional objects exist.
Demo
vcl: