HIT after PURGE & Restart

Nigel Peck np.lists at sharphosting.uk
Sat Apr 15 03:50:38 CEST 2017


This is great, thanks Dridi for all the awesome tips!

Nigel

> On 14 Apr 2017, at 08:11, Dridi Boukelmoune <dridi at varni.sh> wrote:
> 
>> On Thu, Apr 13, 2017 at 11:26 PM, Nigel Peck <np.lists at sharphosting.uk> wrote:
>> 
>> Thanks for this, really helpful to have the assistance. There's no chance
>> that the object was requested between the purge and hit, because those log
>> entries are from a simple varnishlog query for the specific URI.
>> 
>> varnishlog -d -q "ReqURL eq '/media/images/logo-glyph-2x.png'"
>> 
>> So it would be shown in the log.
> 
> Focus on the URL might be a hint of something going on with the host
> header. Since your VCL relies solely on the built-in for hashing,
> please bear in mind that the host is part of the cache key. You can
> enable Hash records in the log (man varnishd) or simply look at the
> Host+URL combo.
> 
>> I don't think there's anything in my VCL that is causing this. But I'm
>> including it all below in case and to help in diagnosing this.
>> 
>> Regarding the test, Dridi, I wouldn't expect that to fail.
> 
> I went ahead and tried to tickle the purge further by purging a
> resource while it's referenced by another transaction and couldn't
> get a spurious hit. I needed some synchronization and since 4.0 is
> EOL and it doesn't have barriers in varnishtest, I didn't feel like
> adapting the test to the good old semas.
> 
>> This is not
>> happening in the majority of cases. But what is happening is that I'm
>> monitoring the log for any misses, and noticed that there are unexplainable
>> misses sometimes. I have a script that issues a PURGE request for every URI
>> on the site, with TTL being set to 7 days, so nothing should be getting
>> missed, yet sometimes things are. After a few days looking at these misses
>> from various angles, to try and work out what's going on, the description in
>> my original message *seems* to be what is happening. There is no Vary issue
>> since nothing is varied on, and all cookies are removed in VCL_recv. They
>> are definitely being cached with the 7d TTL. So there should be no need for
>> a miss.
> 
> Regarding unexpected misses, objects could be evicted forcefully to
> make space during insertions. See n_lru_nuked (man varnish-counters).
> 
>> The real issue for me is the miss on something that has been purged and
>> re-cached a short time before, but the purge and subsequent HIT seems to be
>> related to the problem.
> 
> Yes, but with truncated logs, it's hard to tell further.
> 
>> I just checked the log again and there are no fresh misses since yesterday,
>> which confirms the theory that this is related to the PURGE and otherwise
>> all ok.
>> 
>> I also included below a second example of the same thing from yesterday.
>> It's not a high traffic site, so I may need to spend some more time
>> gathering info, but I think I have enough to present to you, hence the
>> query. Thanks again.
> 
> Please don't send more, we're no longer supporting 4.0 and I would
> recommend an upgrade to 4.1, especially with VCL looking simple
> enough.
> 
>> =======
>> VCL
>> (very simple as mentioned)
>> =======
>> 
>> vcl 4.0;
>> import std;
>> 
>> # Default backend definition. Set this to point to your content server.
>> backend default {
>>    .host = "x.x.x.x";
>>    .port = "80";
>> }
>> 
>> # Access list for purging, local only
>> acl purgers {
>>    "127.0.0.1";
>>    "x.x.x.x";
>> }
>> 
>> # Process any "PURGE" requests converting
>> # them to GET and restarting
>> sub vcl_purge {
>>    set req.method = "GET";
>>    return (restart);
>> }
>> 
>> sub vcl_synth {
>>    # Handle 301 redirects, taking reason as the URL
>>    # and then replacing it with the standard reason
>>    # Recommended at:
>>    # https://varnish-cache.org/tips/vcl/redirect.html
>>    if (resp.status == 301) {
>>        set resp.http.location = resp.reason;
>>        set resp.reason = "Moved Permanently";
>>        return (deliver);
>>    }
>> }
>> 
>> sub vcl_recv {
>>    # Server_Name was here
>>    if (req.restarts == 0) {
>>        set req.http.X-Processed-By = "Server_Name";
>>    }
> 
> You can use the server.identity variable instead of hard-coding it in
> VCL (see man vcl).
> 
>>    # allow PURGE from localhost and x.x.x.x
>>    if (req.method == "PURGE") {
>>        if (!client.ip ~ purgers) {
>>            return (synth(405, "Purging not allowed for " + client.ip));
>>        }
>>        return (purge);
>>    }
>>    # Forward client's IP to the backend
>>    if (req.restarts == 0) {
>>        if (req.http.X-Real-IP) {
>>            # Do nothing, we already have all we need recorded
>>        } elsif (req.http.X-Forwarded-For) {
>>            set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " +
>> client.ip;
>>        } else {
>>            set req.http.X-Forwarded-For = client.ip;
>>        }
>>    }
> 
> This is Varnish 4.0, you don't need to update the XFF header in VCL.
> 
>>    # Redirect non-HTTPS to HTTPS
>>    # Identified by the fact it does not have the X-Forwarded-Port header
>>    if (req.http.X-Forwarded-Port != "443") {
>>        return (synth(301, "https://www.example.com" + req.url));
>>    }
>> 
>>    # Unset all cookies
>>    unset req.http.Cookie;
>> 
>> }
>> 
>> sub vcl_backend_response {
>> 
>>    # Server_Name was here
>>    set beresp.http.X-Processed-By = "Server_Name";
> 
> See comment above about the server.identity variable.
> 
>> 
>>    # Don't cache 404 responses
>>    if ( beresp.status == 404 ) {
>>        set beresp.ttl = 120s;
>>        set beresp.uncacheable = true;
>>        return (deliver);
>>    }
>> 
>>    # Compress appropriate responses
>>    if (beresp.http.content-type ~
>> "\b((text/(html|plain|css|javascript|xml|xsl))|(application/(javascript|xml|xhtml\+xml)))\b")
>> {
>>        set beresp.do_gzip = true;
>>    }
>> 
>>    # Set long TTL and grace time for 200 and 304 responses
>>    if ( beresp.status == 200 || beresp.status == 304 ) {
>> 
>>        # Allow stale content, in case the backend goes down
>>        set beresp.grace = 6h;
>> 
>>        # This is how long Varnish will keep cached content
>>        set beresp.ttl = 7d;
>>    }
>> 
>> }
>> 
>> sub vcl_deliver {
>>    # Send special headers that indicate the cache status of each response
>>    if (obj.hits > 0) {
>>        set resp.http.X-Cache = "HIT";
>>        set resp.http.X-Cache-Hits = obj.hits;
>>    } else {
>>        set resp.http.X-Cache = "MISS";
>>    }
> 
> You don't need a shiny HIT or MISS in the response. The X-Varnish
> header will tell you that already: one id is a miss, two of them a
> hit.
> 
> Dridi




More information about the varnish-misc mailing list