在设置和配置了 Varnish Cache 来处理单个站点的缓存后,我正在考虑扩展该服务以覆盖跨多个 Web 服务器运行的多个站点,每个站点依次使用 NameVirtualHost 运行多个 vHost。以下是我想要执行的操作的粗略图表。
有人能建议我如何做到这一点以及如何确保 Varnish 将请求路由到正确的后端,因为我尝试让 Varnish 根据传入 URL 处理多个后端时遇到了问题,但我认为我设置了错误的 VCL,导致了各种令人兴奋的问题。
请注意,我不想使用 Varnish负载均衡在服务器之间。这可能会在以后实现,或者我可能会在 Varnish 实例集群前面安装一个负载均衡器。
解决了
这是我最终使用的 VCL。它有点冗长和费力,如果有人能提供优化它的建议,我将不胜感激。
# Varnish - Shared caching cluster
#
backend live {
.host = "sharedserver1.example.com";
.port = "80";
}
backend staging {
.host = "sharedserver2.example.com";
.port = "80";
}
acl purge {
"localhost";
"127.0.0.1";
}
sub vcl_recv {
# If it's NOT a dev site or something weird, direct to the live backend.
if(req.http.host !~ ".dev.example.com") {
set req.backend = live;
return (lookup);
}
# Else, direct it to staging backend and bypass the cache.
else {
set req.backend = staging;
return (pass);
}
# Don't cache search pages or any other dynamic content/forms
# Check if backend is healthy, otherwise say 'sod it' and serve outdated content for X hours.
if (req.backend.healthy) {
set req.grace = 30s;
}
else {
set req.grace = 24h;
}
# Allow stale items to be served for 8 hours
#set resp.grace = 8h;
## Remove the X-Forwarded-For header if it exists.
remove req.http.X-Forwarded-For;
set req.http.X-Forwarded-For = client.ip;
# Single-file PURGE commands
if (req.request == "PURGE") {
if(!client.ip ~ purge) {
error 405 "Not allowed";
}
return (lookup);
}
# Nuclear option: BAN
if (req.request == "BAN") {
# Same ACL check as above:
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
# Clear any cached object containing req.url
ban("req.url ~ " + req.url);
# Clear any cached object matching req.url
ban("req.url == " + req.url);
# Clear any cached object matching req.url AND matching the hostname
ban("req.http.host == " + req.http.host + "&& req.url == " + req.url);
# Throw a synthetic page so the
# request won't go to the backend.
error 200 "Ban added";
}
if (req.http.Accept-Encoding) {
if (req.http.Accept-Encoding ~ "gzip") {
# If browser supports gzip strip other encodings from request
set req.http.Accept-Encoding = "gzip";
}
else if (req.http.Accept-Encoding ~ "deflate") {
# If browser supports deflate strip other encodings from request
set req.http.Accept-Encoding = "deflate";
}
else {
# Unknown encoding in header, remove it
unset req.http.Accept-Encoding;
}
}
# Ignore requests for fresh content; cache everything.
unset req.http.Cache-Control;
unset req.http.Max-Age;
unset req.http.Pragma;
unset req.http.Cookie;
# Strip hash, server doesn't need it.
if (req.url ~ "\#") {
set req.url=regsub(req.url,"\#.*$","");
}
# Strip out Google related parameters
if(req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=") {
set req.url=regsuball(req.url,"&(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)","");
set req.url=regsuball(req.url,"\?(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)","?");
set req.url=regsub(req.url,"\?&","?");
set req.url=regsub(req.url,"\?$","");
}
# Strip cookies for static files:
if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)(\?[a-z0-9]+)?$") {
unset req.http.Cookie;
return(lookup);
}
# Remove has_js and Google Analytics __* cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
# Remove a ";" prefix, if present.
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
# Remove empty cookies.
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
}
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged!";
}
}
sub vcl_hash {
if (req.http.Cookie) {
#set req.hash += req.http.Cookie;
#hash_data(req.url);
hash_data(req.http.cookie);
}
}
sub vcl_fetch {
# If backend is dead DO NOT CACHE 404s
if (beresp.status == 404) {
set beresp.ttl = 0s;
}
# Strip cookies for static files:
if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$") {
unset beresp.http.set-cookie;
}
# Varnish determined the object was not cacheable
if (!beresp.ttl > 0s) {
set beresp.http.X-Cacheable = "NO:Not Cacheable";
} elsif(req.http.Cookie ~"(UserID|_session)") {
# You don't wish to cache content for logged in users
set beresp.http.X-Cacheable = "NO:Got Session";
return(hit_for_pass);
} elsif ( beresp.http.Cache-Control ~ "private") {
# You are respecting the Cache-Control=private header from the backend
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
return(hit_for_pass);
} elsif ( beresp.ttl < 1s ) {
# You are extending the lifetime of the object artificially
set beresp.ttl = 300s;
set beresp.grace = 300s;
set beresp.http.X-Cacheable = "YES:Forced";
} else {
# Varnish determined the object was cacheable
set beresp.http.X-Cacheable = "YES";
}
set beresp.http.x-url = req.url;
# Allow stale items to be served for 8 hours
set beresp.grace = 30s;
set beresp.http.x-host = req.http.host;
return(deliver);
}
sub vcl_deliver {
remove resp.http.X-Varnish;
remove resp.http.Via;
remove resp.http.Age;
unset resp.http.x-host;
remove resp.http.X-Cacheable;
## We'd like to hide the X-Powered-By headers. Nobody has to know we can run PHP and have version xyz of it.
remove resp.http.X-Powered-By;
}
sub vcl_miss {
if (!req.backend.healthy) {
return (error);
}
if (req.request == "PURGE") {
purge;
error 404 "Not In Cache";
}
}
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "PURGE on a missed object";
}
}
sub vcl_error {
#if (!req.backend.healthy && obj.status != 200 && obj.status != 403 && obj.status != 404 && obj.status != 301 && obj.status != 302) {
if (obj.status != 200 && obj.status != 403 && obj.status != 404 && obj.status != 301 && obj.status != 302) {
#if (!req.backend.healthy && obj.status!=200) {
synthetic{"
<!doctype html>
<html>
<body><h1>it's dead,dave</h1></body>
</html>
"};
return (deliver);
}
}
答案1
因此,在 VCL 文件中,首先简单地定义后端,并像这样命名
backend lorem {
.host = "10.0.0.1";
.port = "8088";
}
然后在 vcl_recv 部分中定义它
if(req.http.host ~ "loren.com"){
set req.backend = nginx;
return(pass);
}
这会将所有到 loren.com 的流量(基于主机名)发送到定义的后端。
为不同的站点定义不同的后端,它就会很好地发挥作用。