在以前的公司曾安装过 Varnish,可惜还没摸热就离职了,这次接着倒腾了下 Varnish,并搭建成功,特来记录下,以备后用。
一、测试环境
系统版本:CentOS 6.4 x64
WEB 环境:Nginx+PHP+MySQL
Varnish:3.0
工作原理:简单的说,在本次测试中,Varnish 将来自 80 的请求转发到后端的 nginx8080 端口,当匹配到请求是 jpg、css、js 等静态文件时,将会进入缓存中查找,若未找到则将请求发给后端的 nginx 处理,并缓存此次请求的文件,若下次再次出现相同请求时(通过哈希校验),将直接从缓存中调用。因为 Varnish 缓存处于内存当中,所以读取速度是硬盘无法比拟的,从而实现了 HTTP 加速(Ps:本文为单台主机测试)。
二、安装 Varnish
之前博客已经写过安装 Varnish 相关文章,就不赘述了,详情:http://zhangge.net/2044.html
三、修改 nginx 配置
在安装 varnish 之前,lnmp 环境已经搭建 OK,所以只要把 nginx 所有的监听端口改成 8080 即可。
vim 编辑 /usr/local/nginx/conf/nginx.conf 把 listen 80 改成 listen 8080,然后执行:
/usr/local/nginx/sbin/nginx -s reload 重新加载 nginx 即可,记得使用 netstat -nutlp | grep nginx 查看是否生效。
四、编写 vcl 配置
稍微修改了下《Varnish+Nginx 配置----Varnish》一文中分享的 vcl 配置:
#vim /usr/local/varnish/etc/vcl.conf
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
|
# This is a basic VCL configuration file for varnish. See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition. Set this to point to your content
# server.
backend tgweb {
.host = "0.0.0.0";
.port = "80";
.connect_timeout = 20s;
.first_byte_timeout = 20s;
.between_bytes_timeout = 20s;
}
#允许刷新缓存的规则
#acl purgeAllow {
# 只能本机进行刷新
# "localhost";
#}
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
sub vcl_recv {
#判断请求主机,跳转到相应后端服务器
#if(req.http.host ~ "^(.*)(zhangge.net)")
#{
# set req.backend=tgweb;
#}else{
# error 408 "Hostname not found";
#}
#grace缓存过期仍存放
# 若backend是健康的,则仅grace 5s,如果backend不健康,则grace 1m。
# 这里,5s的目的是为了提高高并发时的吞吐率;
# 1m的目的是,backend挂了之后,还能继续服务一段时间,期望backend挂的不要太久。。。
if (req.backend.healthy) {
set req.grace = 5s;
} else {
set req.grace = 1m;
}
#刷新缓存的处理
#if (req.request == "PURGE"){
# if(!client.ip ~ purgeAllow) {
# error 405 "Not allowed.";
# }
# #转到hit或者miss处理
# return (lookup);
#}
#移除一些特定格式的cookie
if (req.url ~ "^(.*)\.(jpg|png|gif|jpeg|flv|bmp|gz|tgz|bz2|tbz|js|css|html|htm)($|\?)" ) {
#移除cookie,以便能缓存到varnish
unset req.http.cookie;
}
#Accept-Encoding 是浏览器发给服务器,声明浏览器支持的编码类型的
#修正客户端的Accept-Encoding头信息
#防止个别浏览器发送类似 deflate, gzip
if (req.http.Accept-Encoding) {
if (req.url ~ "^(.*)\.(jpg|png|gif|jpeg|flv|bmp|gz|tgz|bz2|tbz)($|\?)" ) {
remove req.http.Accept-Encoding;
}else if (req.http.Accept-Encoding ~ "gzip"){
set req.http.Accept-Encoding = "gzip";
} else if (req.http.Accept-Encoding ~ "deflate"){
set req.http.Accept-Encoding = "deflate";
} else if (req.http.Accept-Encoding ~ "sdch"){
#chrome新增加的压缩
set req.http.Accept-Encoding = "sdch";
}else {
remove req.http.Accept-Encoding;
}
}
#首次访问增加X-Forwarded-For头信息,方便后端程序获取客户端ip
if (req.restarts == 0) {
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;
}
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization) {
/* Not cacheable by default */
return (pass);
}
#js,css文件都有Cookie,不能每次都去后台服务器去取
#if (req.http.Cookie) {
# /* Not cacheable by default */
# return (pass);
#}
#如果请求的是动态页面直接转发到后端服务器
if (req.url ~ "^(.*)\.(php|jsp|do|aspx|asmx|ashx)($|.*)") {
return (pass);
}
return (lookup);
}
sub vcl_pipe {
# Note that only the first request to the backend will have
# X-Forwarded-For set. If you use X-Forwarded-For and want to
# have it set for all requests, make sure to have:
# set bereq.http.connection = "close";
# here. It is not set by default as it might break some broken web
# applications, like IIS with NTLM authentication.
return (pipe);
}
#放过,让其直接去后台服务器请求数据
sub vcl_pass {
return (pass);
}
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
#支持压缩的要增加,防止发送给不支持压缩的浏览器压缩的内容
if(req.http.Accept-Encoding){
hash_data(req.http.Accept-Encoding);
}
return (hash);
}
#缓存服务器lookup查找命中:hit
sub vcl_hit {
#刷新缓存的请求操作,设置TTL为0,返回处理结果代码
#if (req.request == "PURGE") {
# set obj.ttl = 0s;
# error 200 "Purged.";
# }
#缓存服务器命中后(查找到了)
return (deliver);
}
#缓存服务器lookup查找没有命中:miss
sub vcl_miss {
#刷新缓存的请求操作,
#if (req.request == "PURGE") {
# error 404 "Not in cache.";
#}
#缓存服务器没有命中(去后台服务器取)
return (fetch);
}
#从后台服务器取回数据后,视情况是否进行缓存
sub vcl_fetch {
#如果请求的是动态页面直接发转发
#动态请求回来的,一定要放在前面处理
if (req.url ~ "^(.*)\.(php|jsp|do|aspx|asmx|ashx)($|.*)") {
set beresp.http.Cache-Control="no-cache, no-store";
unset beresp.http.Expires;
return (deliver);
}
# 仅当该请求可以缓存时,才设置beresp.grace,若该请求不能被缓存,则不设置beresp.grace
if (beresp.ttl > 0s) {
set beresp.grace = 1m;
}
if (beresp.ttl <= 0s ||
beresp.http.Set-Cookie ||
beresp.http.Vary == "*") {
/*
* Mark as "Hit-For-Pass" for the next 2 minutes
*/
set beresp.ttl = 120 s;
#下次请求时不进行lookup,直接pass
return (hit_for_pass);
}
#设置从后台服务器获得的特定格式文件的缓存TTL
if (req.url ~ "^(.*)\.(pdf|xls|ppt|doc|docx|xlsx|pptx|chm|rar|zip)($|\?)")
{
#移除服务器发送的cookie
unset beresp.http.Set-Cookie;
#加上缓存时间
set beresp.ttl = 30d;
return (deliver);
}else if(req.url ~ "^(.*)\.(bmp|jpeg|jpg|png|gif|svg|png|ico|txt|css|js|html|htm)($|\?)"){
#移除服务器发送的cookie
unset beresp.http.Set-Cookie;
#加上缓存时间
set beresp.ttl = 15d;
return (deliver);
}else if(req.url ~ "^(.*)\.(mp3|wma|mp4|rmvb|ogg|mov|avi|wmv|mpeg|mpg|dat|3pg|swf|flv|asf)($|\?)"){
#移除服务器发送的cookie
unset beresp.http.Set-Cookie;
#加上缓存时间
set beresp.ttl = 30d;
return (deliver);
}
#从后台服务器返回的response信息中,没有缓存的,不缓存
if (beresp.http.Pragma ~"no-cache" || beresp.http.Cache-Control ~"no-cache" || beresp.http.Cache-Control ~"private") {
return (deliver);
}
return (deliver);
}
#缓存服务器发送到客户端前调用
sub vcl_deliver {
#下面是添加一个Header标识,以判断缓存是否命中。
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT from TG.varnish-cache.jjcj.com";
#set resp.http.X-Varnish = "HIT from TG.varnish-cache.jjcj.com";
} else {
set resp.http.X-Cache = "MISS from TG.varnish-cache.jjcj.com";
#set resp.http.X-Varnish = "MISS from TG.varnish-cache.jjcj.com";
}
#去掉不是必须的header
unset resp.http.Vary;
unset resp.http.X-Powered-By;
unset resp.http.X-AspNet-Version;
return (deliver);
}
sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
set obj.http.Retry-After = "5";
synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>"} + obj.status + " " + obj.response + {"</title>
</head>
<body>
<h1>Error "} + obj.status + " " + obj.response + {"</h1>
<p>"} + obj.response + {"</p>
<h3>Guru Meditation:</h3>
<p>XID: "} + req.xid + {"</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
"};
return (deliver);
}
sub vcl_init {
return (ok);
}
sub vcl_fini {
return (ok);
}
|
Ps:该配置文件基本都有详细说明,根据实际情况修改下即可。
五、启动 Varnish
执行如下命令启动 Varnish:
1
|
/usr/local/varnish/sbin/varnishd -f /usr/local/varnish/etc/vcl.conf -s malloc,2048m -T 127.0.0.1:200 -a 0.0.0.0:80
|
六、测试效果
测试很简单:
①、打开谷歌浏览器,按下 F12 进入开发者模式,并点击切换到 network 界面,如图:
②、在地址栏输入测试服务器的 ip,并打开,可以看到 network 里面已经出现页面相关文件的信息:
③、在列表中找到并点击一个静态文件,比如 jpg 或 js 文件,看到 Varnish 信息则为搭建成功:
从图中可以看出,此时还是 MISS 状态,说明这是第一次打开,还未进行缓存。
④、按下 F5 刷新页面后,再次点击这个静态文件,可以看到该文件已经是 HIT 命中状态了,说明文件缓存成功:
⑤、继续查看其它静态文件,比如 jpg、css、png 等文件,均可以发现已经是 HIT 状态了。
七、写在最后
从测试可以看出,Varnish 适合静态文件比较多,而 WEB 服务器 IO 又存在严重瓶颈时的加速。本文为单台主机的简单测试,并未深入研究 varnish 的其他功能配置,希望可以给初次接触 Varnish 搭建的童鞋提供一些帮助。