Caching 清漆:在发布数据后清除缓存
我有一个位于Varnish后面的Plone网站。除了一件事,一切都正常 这是一个动态的网站,因此将不时有新的内容。情况如下: 我有一个显示项目列表的页面。此页已被缓存。因此,我通过某种形式添加了另一个项目,并返回到同一页面,但新项目未显示。这是因为显示的页面来自缓存,并且仍在其TTL内 如何确保在提交新项目时,从缓存中清除该页面,并显示后端服务器中包含新项目的新页面 我的简单VCL如下所示:Caching 清漆:在发布数据后清除缓存,caching,varnish,varnish-vcl,Caching,Varnish,Varnish Vcl,我有一个位于Varnish后面的Plone网站。除了一件事,一切都正常 这是一个动态的网站,因此将不时有新的内容。情况如下: 我有一个显示项目列表的页面。此页已被缓存。因此,我通过某种形式添加了另一个项目,并返回到同一页面,但新项目未显示。这是因为显示的页面来自缓存,并且仍在其TTL内 如何确保在提交新项目时,从缓存中清除该页面,并显示后端服务器中包含新项目的新页面 我的简单VCL如下所示: backend default { .host = "127.0.0.1"; .po
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
if (req.request != "GET" && req.request != "HEAD") {
# We only deal with GET and HEAD by default
return (pass);
}
# remove unnecessary cookies
if (req.http.cookie ~ "wc.cookiecredentials|Path|Domain") {
# found wc.cookiecredentials in request, passing to backend server
return (lookup);
} else {
unset req.http.cookie;
}
}
sub vcl_fetch {
#unset beresp.http.Set-Cookie;
set beresp.ttl = 12h;
return(deliver);
}
# Routine used to determine the cache key if storing/retrieving a cached page.
sub vcl_hash {
# Do NOT use this unless you want to store per-user caches.
if (req.http.Cookie) {
set req.hash += req.http.Cookie;
}
}
sub vcl_deliver {
# send some handy statistics back, useful for checking cache
if (obj.hits > 0) {
set resp.http.X-Cache-Action = "HIT";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache-Action = "MISS";
}
}
或者简单地说,当我收到POST请求时,如何清除或清除域的整个缓存?要实现这一点,您需要自定义Varnish VCL以处理
清除
请求和Plone CMS,以便在内容更改时向Varnish发出清除请求
Plone开发人员文档在这方面有非常好和全面的文档。您可以根据自己的具体需要进行调整
文档中的示例解释了如何在VCL中创建自定义ACL和regexp清除处理,然后在Plone中使用它清除整个缓存。我从这里的示例中复制了VCL和Plone视图,以防它们在将来某个时候从Plone站点中删除:
acl purge {
"localhost";
# XXX: Add your local computer public IP here if you
# want to test the code against the production server
# from the development instance
}
...
sub vcl_recv {
...
# Allow PURGE requests clearing everything
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
# Purge for the current host using reg-ex from X-Purge-Regex header
purge("req.http.host == " req.http.host " && req.url ~ " req.http.X-Purge-Regex);
error 200 "Purged.";
}
}
然后为Plone创建一个自定义视图,用于发出PURGE
清漆请求:
import requests
from Products.CMFCore.interfaces import ISiteRoot
from five import grok
from requests.models import Request
class Purge(grok.CodeView):
"""
Purge upstream cache from all entries.
This is ideal to hook up for admins e.g. through portal_actions menu.
You can access it as admin::
http://site.com/@@purge
"""
grok.context(ISiteRoot)
# Onlyl site admins can use this
grok.require("cmf.ManagePortal")
def render(self):
"""
Call the parent cache using Requets Python library and issue PURGE command for all URLs.
Pipe through the response as is.
"""
# This is the root URL which will be purged
# - you might want to have different value here if
# your site has different URLs for manage and themed versions
site_url = self.context.portal_url() + "/"
headers = {
# Match all pages
"X-Purge-Regex" : ".*"
}
resp = requests.request("PURGE", site_url + "*", headers=headers)
self.request.response["Content-type"] = "text/plain"
text = []
text.append("HTTP " + str(resp.status_code))
# Dump response headers as is to the Plone user,
# so he/she can diagnose the problem
for key, value in resp.headers.items():
text.append(str(key) + ": " + str(value))
# Add payload message from the server (if any)
if hasattr(resp, "body"):
text.append(str(resp.body))
如前所述,这只是按需清除整个缓存。我不是Plone方面的专家,所以我无法给你一个详细的答案,告诉你如何调整它来清除特定的内容。基本上,您需要确定在特定情况下需要清除哪些页面,然后调整上面的示例,以便在Plone中处理POST
请求时自动发出purge
请求以进行清漆处理
单独在VCL中处理清除(即检测POST调用并基于这些调用清除内容)相当复杂。我相信在Plone中处理逻辑和清除将更加有效
更新:
如果您希望在每次POST
上清除整个缓存,可以按如下方式完成
sub vcl_recv {
if ( req.request == "POST") {
ban("req.http.host == " + req.http.Host);
return(pass);
}
}
现在,每个
POST
请求都会导致缓存在同一主机名下的所有页面从缓存中清除。不过,我建议从长远来看,考虑一下早期的解决方案。当出现POST
时,只清除实际需要清除的页面要高效得多。要完成这一点,您需要自定义Varnish VCL以处理PURGE
请求和Plone CMS,以便在内容更改时向Varnish发出清除请求
Plone开发人员文档在这方面有非常好和全面的文档。您可以根据自己的具体需要进行调整
文档中的示例解释了如何在VCL中创建自定义ACL和regexp清除处理,然后在Plone中使用它清除整个缓存。我从这里的示例中复制了VCL和Plone视图,以防它们在将来某个时候从Plone站点中删除:
acl purge {
"localhost";
# XXX: Add your local computer public IP here if you
# want to test the code against the production server
# from the development instance
}
...
sub vcl_recv {
...
# Allow PURGE requests clearing everything
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
# Purge for the current host using reg-ex from X-Purge-Regex header
purge("req.http.host == " req.http.host " && req.url ~ " req.http.X-Purge-Regex);
error 200 "Purged.";
}
}
然后为Plone创建一个自定义视图,用于发出PURGE
清漆请求:
import requests
from Products.CMFCore.interfaces import ISiteRoot
from five import grok
from requests.models import Request
class Purge(grok.CodeView):
"""
Purge upstream cache from all entries.
This is ideal to hook up for admins e.g. through portal_actions menu.
You can access it as admin::
http://site.com/@@purge
"""
grok.context(ISiteRoot)
# Onlyl site admins can use this
grok.require("cmf.ManagePortal")
def render(self):
"""
Call the parent cache using Requets Python library and issue PURGE command for all URLs.
Pipe through the response as is.
"""
# This is the root URL which will be purged
# - you might want to have different value here if
# your site has different URLs for manage and themed versions
site_url = self.context.portal_url() + "/"
headers = {
# Match all pages
"X-Purge-Regex" : ".*"
}
resp = requests.request("PURGE", site_url + "*", headers=headers)
self.request.response["Content-type"] = "text/plain"
text = []
text.append("HTTP " + str(resp.status_code))
# Dump response headers as is to the Plone user,
# so he/she can diagnose the problem
for key, value in resp.headers.items():
text.append(str(key) + ": " + str(value))
# Add payload message from the server (if any)
if hasattr(resp, "body"):
text.append(str(resp.body))
如前所述,这只是按需清除整个缓存。我不是Plone方面的专家,所以我无法给你一个详细的答案,告诉你如何调整它来清除特定的内容。基本上,您需要确定在特定情况下需要清除哪些页面,然后调整上面的示例,以便在Plone中处理POST
请求时自动发出purge
请求以进行清漆处理
单独在VCL中处理清除(即检测POST调用并基于这些调用清除内容)相当复杂。我相信在Plone中处理逻辑和清除将更加有效
更新:
如果您希望在每次POST
上清除整个缓存,可以按如下方式完成
sub vcl_recv {
if ( req.request == "POST") {
ban("req.http.host == " + req.http.Host);
return(pass);
}
}
现在,每个
POST
请求都会导致缓存在同一主机名下的所有页面从缓存中清除。不过,我建议从长远来看,考虑一下早期的解决方案。当出现POST
时,只清除实际需要清除的页面要有效得多。感谢您的回答@Ketola。是否有一种方法可以在每次收到POST请求时清除整个缓存?确实有。我已经更新了我的答案,以涵盖这一备选方案。不过,这不是一个非常有效的解决方案,在这种情况下,您的缓存命中率永远不会很高。这应该可以满足我的目的。谢谢您的回答@Ketola。是否有一种方法可以在每次收到POST请求时清除整个缓存?确实有。我已经更新了我的答案,以涵盖这一备选方案。不过,这不是一个非常有效的解决方案,在这种情况下,缓存命中率永远不会很高。这应该可以满足我的目的。