1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| vim /usr/local/varnish/default.vcl probe health { .url = "/"; # 检查请求的url路径 .timeout = 3s; # 超时时间3s .interval = 1s; # 访问间隔时间1s .window = 5; # 维持5个窗口 .threshold = 3; # 5个窗口中至少3个是成功的 } backend web1 { # 后端web集群 .host = "172.16.1.13"; .port = "80"; .probe = health; # 添加对本主机的健康检查 .max_connections = 100; }
backend web2 { # 后端web集群 .host = "172.16.1.14"; .port = "80"; .probe = health; # 添加对本主机的健康检查 .max_connections = 100; } acl allow{ # 对于清除缓存的访问控制列表,只允许本地进行清除缓存 "127.0.0.1"; "localhost"; "172.16.1.12"; } import directors; # 导入集群模块 sub vcl_init{ # 导入轮询模块 new back = directors.round_robin(); # 轮询方式为rr back.add_backend(web1); # 轮询web1 back.add_backend(web2); # 轮询web2 }
sub vcl_recv{ # 数据请求模块 set req.backend_hint = back.backend(); # 如果后端站点健康检查为不健康,则屏蔽掉 if(req.method == "PURGE"){ # 如果数据请求的方法为PURGE的情况下 if(client.ip !~ allow){ # 如果客户机ip不在acl允许的访问控制列表中 return(synth(403,"NOT ALLOW")); # 则在主机头中返回状态码403,不允许 } else{ # 反之(客户机ip在acl中) return(purge); # 则清除缓存 } } if(req.http.host ~ "^img"){ # 如果请求的http协议的host以img开头 set req.backend_hint = web1; # 则调度到web1后端 } if(req.http.host ~ "^www"){ # 如果请求的http协议的host以www开头 set req.backend_hint = web2; # 则调度到web2后端 } if(req.url ~ "\.(php|asp|aspx|jsp|do)($|\?)"){ # 如果请求的url为动态数据 return(pass); # 则进入pass模块(去后端索取内容) } if(req.url ~ "\.(css|htm|html|png|gif|jpg)($|\?)"){ # 如果请求的url为静态数据 return(hash); # 则进入hash模块进行hash } if(req.method != "GET" && req.method != "PUT" && req.method != "POST" && req.method != "DELETE" && req.method != "HEAD" ){ # 如果请求的方法非正常 return(pipe); # 则直接到错误页面 } if(req.method != "GET" && req.method != "HEAD"){ # 如果请求的方法是除了get和head以外的方法 return(pass); # 则进入到pass模块(去后端) } if(req.http.Authorization){ # 如果请求头部中存在认证 return(pass); # 则进入到pass模块(去后端) } if(req.http.Accept-Encoding){ # 如果浏览器支持编码 if(req.url ~ "\.(png|gif|jpg|jpeg|gz|)"){ # 如果请求的url中包含这些格式的内容 unset req.http.Accept-Encoding; # 则不进行压缩 } elseif(req.http.Accept-Encoding ~ "gzip"){ # 如果浏览器支持的编码格式为gzip set req.http.Accept-encoding = "gzip"; # 则使用gzip压缩 } elseif(req.http.Accept-Encoding ~ "deflate"){ # 如果浏览器支持的编码格式为deflate set req.http.Accept-Encoding = "deflate"; # 则使用zlib压缩 } else{ # 否则 unset req.http.Accept-Encoding; # 不进行压缩 } } } # 配置pipe模块 sub vcl_pipe{ return(pipe); # 进入到此模块的,直接退出 } # 配置pass动态数据模块 sub vcl_pass{ return(fetch); # 进入到此模块的,去后端索取内容 } # 配置hash静态数据模块 sub vcl_hash{ hash_data(req.url); # 进入到此模块的对url进行hash if(req.http.host){ # 如果请求的主机头中存在host部分 hash_data(req.http.host); # 则对host进行hash } else{ # 如果不存在 hash_data(server.ip); # 则对ip进行hash if(req.http.Accept-Encoding ~ "gzip"){ # 如果浏览器的编码为gzip hash_data("gzip"); # 则对gzip文件进行hash } elseif(req.http.Accept-Encoding ~ "deflate"){ # 如果浏览器的编码为deflate hash_data("deflate"); # 则对deflate进行hash } } } # 配置hit命中模块 sub vcl_hit{ return(deliver); # 进入到hit模块中,则直接返回客户端数据 } # 配置miss未命中模块 sub vcl_miss{ return(fetch); # 进入到miss模块中,则进入后端获取内容 } # 配置后端节点模块 sub vcl_backend_response{ if(bereq.url ~ "\.(php|asp|jsp|do)$"){ # 如果返回的url中带有这些后缀的(动态数据) set beresp.uncacheable = true; # 不在本地进行缓存 } if(bereq.url ~ "\.(css|js|html|png|gif)"){ # 如果返回的url中带有这些后缀的(静态数据) set beresp.ttl = 15m; # 将内容在内存中缓存停留15分钟 } if(bereq.url ~ "\.(gz|bz2|mp3)"){ # 如果返回的url中带有这些后缀的 set beresp.ttl = 30m; # 将内容在内存中缓存停留30分钟 } return(deliver); # 其余的直接交给客户端 } # 配置清除缓存的模块 sub vcl_purge{ return(synth(200,"success")); # 进入到purge模块的返回状态码200, 信息success } # 配置响应客户端 sub vcl_deliver{ if(obj.hits > 0){ # 如果缓存命中次数大于0 set resp.http.X-Cache = "hit"; # varnish返回给客户端的信息头部,新建一条hit } else{ # 反之 set resp.http.X-Cache = "miss"; # varnish返回给客户端的信息头部,新建一条miss } return(deliver); # 正常结束 }
|