varnish 中的内置变量 req repos client server bereq beresp bereq bereq.http.HEADER 由varnish发往backend server 的请求报文指定首部 bereq.request 请求方法 bereq.url bereq.proto: 协议版本 beresp bereq.proto bereq.status: bereq.backend.ip beresp.backend.name beresp.http.HEADER 从backend server 响应报文指定首部 bereq.ttl 后端服务器响应的内容的余下的生存时长;
官方文档
http://www.varnish-cache.org/trac/wiki/VCLExampleDirector
支持虚拟主机: if (req.http.host == "www.fengpic.com") { } 强制对某些资源的请求,不检查缓存: /admin /login if (req.url ~ "(?i)^/login" || req.url ~ "(?i)^/admin") { return(pass) } test.html if (req.url ~ "(?i)test.html$") { return(pass) }
sub vcl_recv{
if (req.url ~"(?i)\.(jpg|png|gif)$") {
set req.backend_hint = "fdfs_g1_s1"
else {
set req.backend_hint = "fdfs_g1_s2"
}
}
对域名进行缓存
sub vcl_recv {
if (req.http.host ~ "^(ww.)?example.com%") {
set req.backend_hint = vdir1.backend();
}
}
对多个group进行缓存
backend fdfs_g1_s1 {
.host = "192.168.20.151";
.port = "8080";
.probe = {
.url = "/";
.timeout = 1s;
.interval = 10s;
.window = 5;
.threshold = 2;
}
}
backend fdfs_g1_s2 {
.host = "192.168.20.152";
.port = "8080";
.probe = {
.url = "/";
.timeout = 1s;
.interval = 10s;
.window = 5;
.threshold = 2;
}
}
backend fdfs_g2_s1 {
.host = "192.168.20.153";
.port = "8080";
.probe = {
.url = "/";
.timeout = 1s;
.interval = 10s;
.window = 5;
.threshold = 2;
}
}
backend fdfs_g2_s2 {
.host = "192.168.20.154";
.port = "8080";
.probe = {
.url = "/";
.timeout = 1s;
.interval = 10s;
.window = 5;
.threshold = 2;
}
}
sub vcl_init {
new vdir1 = directors.round_robin();
vdir1.add_backend(fdfs_g1_s1);
vdir1.add_backend(fdfs_g1_s2);
new vdir2 = directors.round_robin();
vdir2.add_backend(fdfs_g2_s1);
vdir2.add_backend(fdfs_g2_s2);
return (ok);
}
sub vcl_recv {
if (req.url ~ "($i)^/group1") {
set req.backend_hint = vdir1.backend();
}
if (req.url ~ "($i)^/group2") {
set req.backend_hint = vdir2.backend();
}
}
首先是必须定义版本号: vcl 4.0。VMOD’s更独立化,官方推荐是加载Standard VMOD’s(std)。 另外director已变为VMOD,如需使用,需要import directors。 vcl_fetch函数被vcl_backend_response和vcl_backend_fetch代替,且req.*不再适用vcl_backend_response,只能使用bereq.*。 至于vcl_backend_fetch貌似没哪个doc见到详细用法。 error变更为return(synth(http_code,message)),req.backend成了req.backend_hint,req.request变更为req.method,obj为只读对象了。 vcl_synth采用resp.*,而非原来的obj.*。 vcl_error变更为vcl_backend_error,必须使用beresp.*,而不是obj.*。 关键字"purge;"命令,已被去除。在vcl_recv使用return(purge)。 hit_for_pass通过set beresp.uncacheable = true;来指定。 vcl_recv必须将lookup变更返回hash,vcl_hash必须将hash变更返回lookup,vcl_pass必须将pass变更返回fetch。 req.backend.healty被std.healthy(req.backend)代替,但是设置不了grace,鸡肋,被抛弃了,现在仅能做的就是keepalive的作用了。 req、bereq,resp、beresp之间不同,可被使用的位置不同。 server.port、client.port分别变更为std.port(server.ip)、std.port(client.ip),跟上面healthy一样,需要import std。 session_linger变更为timeout_linger,sess_timeout变更为timeout_idle,sess_workspace被抛弃了。 remove被完全弃用了,不过我一直用unset的说。 return(restart)变更为return(retry),vcl_backend_fetch会被使用到。 自定义sub函数不能以vcl_开头,调用方式call udf。
1 vcl 4.0; 2 3 import std; 4 import directors; 5 6 backend fdfs_g1_s1 { 7 .host = "192.168.20.151"; 8 .port = "8080"; 9 .probe = { 10 .url = "/"; 11 .timeout = 1s; 12 .interval = 10s; 13 .window = 5; 14 .threshold = 2; 15 } 16 } 17 18 backend fdfs_g1_s2 { 19 .host = "192.168.20.152"; 20 .port = "8080"; 21 .probe = { 22 .url = "/"; 23 .timeout = 1s; 24 .interval = 10s; 25 .window = 5; 26 .threshold = 2; 27 } 28 } 29 30 acl purgers { 31 "localhost"; 32 "127.0.0.1"; 33 } 34 35 sub vcl_init { 36 new vdir = directors.round_robin(); 37 vdir.add_backend(fdfs_g1_s1); 38 vdir.add_backend(fdfs_g1_s2); 39 return (ok); 40 } 41 42 43 sub vcl_recv { 44 45 set req.backend_hint = vdir.backend(); 46 47 if (req.http.x-forwarded-for) { 48 set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; 49 } else { 50 set req.http.X-Forwarded-For = client.ip; 51 } 52 53 if (req.method == "PURGE") { # PURGE请求的处理 54 if (!client.ip ~ purgers) { 55 return(synth(405,"Method not allowed")); 56 } 57 #清理缓存 58 return (purge); 59 } 60 # 禁止缓存的文件 61 if (req.url ~ "\.(php|jsp|do|cgi)$") { 62 return (pass); 63 } 64 65 if (req.method == "PRI") { 66 #/* We do not support SPDY or HTTP/2.0 */ 67 return (synth(405)); 68 } 69 if (req.method != "GET" && 70 req.method != "HEAD" && 71 req.method != "PUT" && 72 req.method != "POST" && 73 req.method != "TRACE" && 74 req.method != "OPTIONS" && 75 req.method != "DELETE") { 76 #/* Non-RFC2616 or CONNECT which is weird. */ 77 return (pipe); 78 } 79 80 if (req.method != "GET" && req.method != "HEAD") { 81 #/* We only deal with GET and HEAD by default */ 82 return (pass); 83 } 84 if (req.http.Authorization || req.http.Cookie) { 85 #/* Not cacheable by default */ 86 return (pass); 87 } 88 return (hash); 89 } 90 91 sub vcl_backend_response { 92 93 if (beresp.http.cache-control !~ "s-maxage") { 94 if (bereq.url ~ "\.(gif|jpeg|jpg|png)$") { 95 set beresp.ttl = 3600s; 96 unset beresp.http.set-cookie; 97 } 98 99 if (bereq.url ~ "\.(css|js)$") { 100 set beresp.ttl = 600s; 101 unset beresp.http.set-cookie; 102 } 103 104 if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|amr|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") { 105 unset beresp.http.set-cookie; 106 set beresp.do_stream = true; 107 set beresp.do_gzip = false; 108 } 109 } else { 110 if (beresp.ttl > 0s) { 111 unset beresp.http.Set-Cookie; 112 } 113 } 114 115 if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Surrogate-control ~ "no-store" || (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "no-cache|no-store|private") || beresp.http.Vary == "*") { 116 set beresp.ttl = 120s; 117 set beresp.uncacheable = true; 118 } 119 120 return (deliver); 121 } 122 123 124 sub vcl_backend_fetch { 125 return (fetch); 126 } 127 128 sub vcl_pipe { 129 # By default Connection: close is set on all piped requests, to stop 130 # connection reuse from sending future requests directly to the 131 # (potentially) wrong backend. If you do want this to happen, you can undo 132 # it here. 133 # unset bereq.http.connection; 134 return (pipe); 135 } 136 137 sub vcl_pass { 138 return (fetch); 139 } 140 141 sub vcl_hash { 142 hash_data(req.url); 143 if (req.http.host) { 144 hash_data(req.http.host); 145 } else { 146 hash_data(server.ip); 147 } 148 return (lookup); 149 } 150 151 sub vcl_purge { 152 return (synth(200, "Purged")); 153 } 154 155 sub vcl_hit { 156 if (obj.ttl >= 0s) { 157 #// A pure unadultered hit, deliver it 158 return (deliver); 159 } 160 if (obj.ttl + obj.grace > 0s) { 161 #// Object is in grace, deliver it 162 #// Automatically triggers a background fetch 163 return (deliver); 164 } 165 #// fetch & deliver once we get the result 166 return (miss); 167 } 168 169 sub vcl_miss { 170 return (fetch); 171 } 172 173 sub vcl_deliver { 174 set resp.http.Via = "cache"; 175 unset resp.http.X-Varnish; 176 set resp.http.Server="cache-server"; 177 unset resp.http.Age; 178 # set resp.http.x-hits = obj.hits; 179 180 if (obj.hits > 0) { 181 set resp.http.X-Cache = "Hit aaaaaa CDN"; 182 }else { 183 set resp.http.X-Cache = "Miss"; 184 } 185 return (deliver); 186 } 187 188 sub vcl_synth { 189 set resp.http.Content-Type = "text/html; charset=utf-8"; 190 set resp.http.Retry-After = "5"; 191 synthetic( {"<!DOCTYPE html> 192 <html> 193 <head> 194 <title>"} + resp.status + " " + resp.reason + {"</title> 195 </head> 196 <body> 197 <h1>Error "} + resp.status + " " + resp.reason + {"</h1> 198 <p>"} + resp.reason + {"</p> 199 <h3>Guru Meditation:</h3> 200 <p>XID: "} + req.xid + {"</p> 201 <hr> 202 <p>Varnish cache server</p> 203 </body> 204 </html> 205 "} ); 206 return (deliver); 207 } 208 209 210 sub vcl_backend_error { 211 set beresp.http.Content-Type = "text/html; charset=utf-8"; 212 set beresp.http.Retry-After = "5"; 213 synthetic( {"<!DOCTYPE html> 214 <html> 215 <head> 216 <title>"} + beresp.status + " " + beresp.reason + {"</title> 217 </head> 218 <body> 219 <h1>Error "} + beresp.status + " " + beresp.reason + {"</h1> 220 <p>"} + beresp.reason + {"</p> 221 <h3>Guru Meditation:</h3> 222 <p>XID: "} + bereq.xid + {"</p> 223 <hr> 224 <p>Varnish cache server</p> 225 </body> 226 </html> 227 "} ); 228 return (deliver); 229 } 230 231 sub vcl_fini { 232 return (ok); 233 }
1 vcl 4.0; 2 3 import std; 4 import directors; 5 6 backend fdfs_g1_s1 { 7 .host = "192.168.20.151"; 8 .port = "8080"; 9 .probe = { 10 .url = "/"; 11 .timeout = 1s; 12 .interval = 10s; 13 .window = 5; 14 .threshold = 2; 15 } 16 } 17 18 backend fdfs_g1_s2 { 19 .host = "192.168.20.152"; 20 .port = "8080"; 21 .probe = { 22 .url = "/"; 23 .timeout = 1s; 24 .interval = 10s; 25 .window = 5; 26 .threshold = 2; 27 } 28 } 29 30 31 backend fdfs_g2_s1 { 32 .host = "192.168.20.113"; 33 .port = "8080"; 34 .probe = { 35 .url = "/"; 36 .timeout = 1s; 37 .interval = 10s; 38 .window = 5; 39 .threshold = 2; 40 } 41 } 42 43 backend fdfs_g2_s2 { 44 .host = "192.168.20.115"; 45 .port = "8080"; 46 .probe = { 47 .url = "/"; 48 .timeout = 1s; 49 .interval = 10s; 50 .window = 5; 51 .threshold = 2; 52 } 53 } 54 55 56 57 acl purgers { 58 "localhost"; 59 "127.0.0.1"; 60 } 61 62 sub vcl_init { 63 new g1vdir = directors.round_robin(); 64 g1vdir.add_backend(fdfs_g1_s1); 65 g1vdir.add_backend(fdfs_g1_s2); 66 67 new g2vdir = directors.round_robin(); 68 g2vdir.add_backend(fdfs_g2_s1); 69 g2vdir.add_backend(fdfs_g2_s2); 70 71 return (ok); 72 } 73 74 75 sub vcl_recv { 76 77 if (req.url ~ "/group1") { 78 set req.backend_hint = g1vdir.backend(); 79 } 80 81 if (req.url ~ "/group2") { 82 set req.backend_hint = g2vdir.backend(); 83 } 84 85 if (req.http.x-forwarded-for) { 86 set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; 87 } else { 88 set req.http.X-Forwarded-For = client.ip; 89 } 90 91 if (req.method == "PURGE") { # PURGE请求的处理 92 if (!client.ip ~ purgers) { 93 return(synth(405,"Method not allowed")); 94 } 95 #清理缓存 96 return (purge); 97 } 98 # 禁止缓存的文件 99 if (req.url ~ "\.(php|jsp|do|cgi)$") { 100 return (pass); 101 } 102 103 if (req.method == "PRI") { 104 #/* We do not support SPDY or HTTP/2.0 */ 105 return (synth(405)); 106 } 107 if (req.method != "GET" && 108 req.method != "HEAD" && 109 req.method != "PUT" && 110 req.method != "POST" && 111 req.method != "TRACE" && 112 req.method != "OPTIONS" && 113 req.method != "DELETE") { 114 #/* Non-RFC2616 or CONNECT which is weird. */ 115 return (pipe); 116 } 117 118 if (req.method != "GET" && req.method != "HEAD") { 119 #/* We only deal with GET and HEAD by default */ 120 return (pass); 121 } 122 if (req.http.Authorization || req.http.Cookie) { 123 #/* Not cacheable by default */ 124 return (pass); 125 } 126 return (hash); 127 } 128 129 sub vcl_backend_response { 130 131 if (beresp.http.cache-control !~ "s-maxage") { 132 if (bereq.url ~ "\.(gif|jpeg|jpg|png)$") { 133 set beresp.ttl = 3600s; 134 unset beresp.http.set-cookie; 135 } 136 137 if (bereq.url ~ "\.(css|js)$") { 138 set beresp.ttl = 600s; 139 unset beresp.http.set-cookie; 140 } 141 142 if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|amr|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") { 143 unset beresp.http.set-cookie; 144 set beresp.do_stream = true; 145 set beresp.do_gzip = false; 146 } 147 } else { 148 if (beresp.ttl > 0s) { 149 unset beresp.http.Set-Cookie; 150 } 151 } 152 153 if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Surrogate-control ~ "no-store" || (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "no-cache|no-store|private") || beresp.http.Vary == "*") { 154 set beresp.ttl = 120s; 155 set beresp.uncacheable = true; 156 } 157 158 return (deliver); 159 } 160 161 162 sub vcl_backend_fetch { 163 return (fetch); 164 } 165 166 sub vcl_pipe { 167 # By default Connection: close is set on all piped requests, to stop 168 # connection reuse from sending future requests directly to the 169 # (potentially) wrong backend. If you do want this to happen, you can undo 170 # it here. 171 # unset bereq.http.connection; 172 return (pipe); 173 } 174 175 sub vcl_pass { 176 return (fetch); 177 } 178 179 sub vcl_hash { 180 hash_data(req.url); 181 if (req.http.host) { 182 hash_data(req.http.host); 183 } else { 184 hash_data(server.ip); 185 } 186 return (lookup); 187 } 188 189 sub vcl_purge { 190 return (synth(200, "Purged")); 191 } 192 193 sub vcl_hit { 194 if (obj.ttl >= 0s) { 195 #// A pure unadultered hit, deliver it 196 return (deliver); 197 } 198 if (obj.ttl + obj.grace > 0s) { 199 #// Object is in grace, deliver it 200 #// Automatically triggers a background fetch 201 return (deliver); 202 } 203 #// fetch & deliver once we get the result 204 return (miss); 205 } 206 207 sub vcl_miss { 208 return (fetch); 209 } 210 211 sub vcl_deliver { 212 set resp.http.Via = "cache"; 213 unset resp.http.X-Varnish; 214 set resp.http.Server="cache-server"; 215 unset resp.http.Age; 216 # set resp.http.x-hits = obj.hits; 217 218 if (obj.hits > 0) { 219 set resp.http.X-Cache = "Hit aaaaaa CDN"; 220 }else { 221 set resp.http.X-Cache = "Miss"; 222 } 223 return (deliver); 224 } 225 226 sub vcl_synth { 227 set resp.http.Content-Type = "text/html; charset=utf-8"; 228 set resp.http.Retry-After = "5"; 229 synthetic( {"<!DOCTYPE html> 230 <html> 231 <head> 232 <title>"} + resp.status + " " + resp.reason + {"</title> 233 </head> 234 <body> 235 <h1>Error "} + resp.status + " " + resp.reason + {"</h1> 236 <p>"} + resp.reason + {"</p> 237 <h3>Guru Meditation:</h3> 238 <p>XID: "} + req.xid + {"</p> 239 <hr> 240 <p>Varnish cache server</p> 241 </body> 242 </html> 243 "} ); 244 return (deliver); 245 } 246 247 248 sub vcl_backend_error { 249 set beresp.http.Content-Type = "text/html; charset=utf-8"; 250 set beresp.http.Retry-After = "5"; 251 synthetic( {"<!DOCTYPE html> 252 <html> 253 <head> 254 <title>"} + beresp.status + " " + beresp.reason + {"</title> 255 </head> 256 <body> 257 <h1>Error "} + beresp.status + " " + beresp.reason + {"</h1> 258 <p>"} + beresp.reason + {"</p> 259 <h3>Guru Meditation:</h3> 260 <p>XID: "} + bereq.xid + {"</p> 261 <hr> 262 <p>Varnish cache server</p> 263 </body> 264 </html> 265 "} ); 266 return (deliver); 267 } 268 269 sub vcl_fini { 270 return (ok); 271 }