【问题标题】:Prevent Varnish from Caching Scheduled Gravity Forms防止清漆缓存预定的重力形式
【发布时间】:2014-07-08 23:28:44
【问题描述】:

我们遇到了一个问题,即用户在 Wordpress 中安排 Gravity Forms 在某些日期/时间可用和不可用。问题是 Varnish 正在缓存页面,所以除非我们手动进入并重新保存页面(保存时会导致页面清除)或手动清除缓存,否则这些计划的表单不会按预期出现或消失。除了每晚清除整个缓存或其他一些“黑客”(例如制作未缓存的表单子站点)之外,我似乎找不到解决此问题的方法。

下面是我们非常丑陋的 VCL 文件供参考。

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

# Only allow purging from specific IPs
include "lib/purge.vcl";
acl purge {
    "localhost";
    "127.0.0.1";
}

# Cache static assets
include "lib/static.vcl";

sub vcl_recv {
    # Handle compression correctly. Different browsers send different
    # "Accept-Encoding" headers, even though they mostly support the same
    # compression mechanisms. By consolidating compression headers into
    # a consistent format, we reduce the cache size and get more hits.
    # @see: http:// varnish.projects.linpro.no/wiki/FAQ/Compression
    if (req.http.Accept-Encoding) {
        if (req.http.Accept-Encoding ~ "gzip") {
            # If the browser supports it, we'll use gzip.
            set req.http.Accept-Encoding = "gzip";
        }
        else if (req.http.Accept-Encoding ~ "deflate") {
            # Next, try deflate if it is supported.
            set req.http.Accept-Encoding = "deflate";
        }
        else {
            # Unknown algorithm. Remove it and send unencoded.
            unset req.http.Accept-Encoding;
        }
    }

    # Set client IP
    if (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;
    }

    # Check if we may purge (only localhost)
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        return(lookup);
    }

    if (req.request != "GET" &&
        req.request != "HEAD" &&
        req.request != "PUT" &&
        req.request != "POST" &&
        req.request != "TRACE" &&
        req.request != "OPTIONS" &&
        req.request != "DELETE") {
            # /* Non-RFC2616 or CONNECT which is weird. */
            return (pipe);
    }

    if (req.request != "GET" && req.request != "HEAD") {
        # /* We only deal with GET and HEAD by default */
        return (pass);
    }

    # admin users always miss the cache
    if( req.url ~ "^/wp-(login|admin)" ||
        req.http.Cookie ~ "wordpress_logged_in_" ){
            return (pass);
    }

    # Remove cookies set by Google Analytics (pattern: '__utmABC')
    if (req.http.Cookie) {
        set req.http.Cookie = regsuball(req.http.Cookie,
            "(^|; ) *__utm.=[^;]+;? *", "\1");
        if (req.http.Cookie == "") {
            remove req.http.Cookie;
        }
    }

    # always pass through POST requests and those with basic auth
    if (req.http.Authorization || req.request == "POST") {
        return (pass);
    }

    # Do not cache these paths
    if (req.url ~ "^/wp-cron\.php$" ||
        req.url ~ "^/xmlrpc\.php$" ||
        req.url ~ "^/wp-admin/.*$" ||
        req.url ~ "^/wp-includes/.*$" ||
        req.url ~ "\?s=") {
            return (pass);
    }

    # Define the default grace period to serve cached content
    set req.grace = 30s;

    # Allow native WP page passwords to function
    if( req.http.Cookie ~ "wp-postpass_" ){
            return (pass);
    }

    # Allow password protected plugin to function
    if( req.http.Cookie ~ "bid_" ){

    # Drop any other cookies
    if (!(req.url ~ "wp-(login|admin)")) {
       unset req.http.cookie;
    }

    # By ignoring any other cookies, it is now ok to get a page
    unset req.http.Cookie;
    return (lookup);
}

sub vcl_fetch {
    # remove some headers we never want to see
    unset beresp.http.Server;
    unset beresp.http.X-Powered-By;

    # only allow cookies to be set if we're in admin area
    if (!(req.url ~ "wp-(login|admin)")) {
        unset beresp.http.set-cookie;
    }

    # don't cache response to posted requests or those with basic auth
    if ( req.request == "POST" || req.http.Authorization) {
        return (hit_for_pass);
    }

    # don't cache search results
    if( req.url ~ "\?s=" ){
        return (hit_for_pass);
    }

    # only cache status ok
    if ( beresp.status != 200 ) {
        return (hit_for_pass);
    }

    # If our backend returns 5xx status this will reset the grace time
    # set in vcl_recv so that cached content will be served and
    # the unhealthy backend will not be hammered by requests
    if (beresp.status == 500) {
        set beresp.grace = 60s;
        return (restart);
    }

    # GZip the cached content if possible
    if (beresp.http.content-type ~ "text") {
        set beresp.do_gzip = true;
    }

    # if nothing abovce matched it is now ok to cache the response
    set beresp.ttl = 24h;
    return (deliver);
}
sub vcl_deliver {
    # remove some headers added by varnish
    unset resp.http.Via;
    unset resp.http.X-Varnish;
}

sub vcl_hit {
    # Set up invalidation of the cache so purging gets done properly
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
    return (deliver);
}

sub vcl_miss {
    # Set up invalidation of the cache so purging gets done properly
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
    return (fetch);
}

sub vcl_error {
    if (obj.status == 503) {
                # set obj.http.location = req.http.Location;
                set obj.status = 404;
        set obj.response = "Not Found";
                return (deliver);
    }
}

【问题讨论】:

    标签: wordpress caching varnish


    【解决方案1】:

    最简单的解决方案是根本不缓存带有表单的页面。例如:

    sub vcl_recv {
        if( req.url ~ "^/(contact|order)" )
            return (pass);
        }
    }
    
    sub vcl_fetch {
        if( req.url ~ "^/(contact|order)" )
            return (hit_for_pass);
        }
    }
    

    或者,您可以指定表单页面的 Expires 标题,以便在表单超出计划时它们过期。不过,这需要对 Gravity Forms 插件进行更改。

    第三个选项是为使用表单的页面设置一个比您现在默认的 24 小时更短的 TTL。例如 15 分钟。这样,它们仍会被缓存,但在预定时间之后的 15 分钟内不可用。

    【讨论】:

    • 由于这是大型 Wordpress 安装的一部分,我试图避免不缓存特定站点或页面集,但这是我慢慢倾向于做的事情,因为我似乎找不到表单的唯一标识符。
    • 作为一种解决方法,我们刚刚在计划表单的大用户网站上设置了 hit_for_pass。
    • 这确实是一个相当激烈的措施,也可能对性能造成很大影响。在你的情况下,我肯定会考虑改变重力形式,以便设置自定义 Expires-headers,或者只是 Cache-control: private, max-age=0
    猜你喜欢
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多