架構
當client user 有一的web request時, 會先經由cache server查看該要求資料是否有在自已cache 暫存裡面, 如果有則直接回應給client user, 反之則向後端web server要求資料然後自已回存一份,然後再回應給client user. 這裡varnish cache server 將扮演前端loadbalance及reverse proxy角色, 如果後端有任一台web server掛了或沒反應, varnish cache server第一時間則會知道, 就不會把資料後down掉那台web server送了!
1. 建立user/group
#groupadd varnish
#useradd -g varnish varnish
2. 建立cache目錄
#mkdir -p /var/varnish_cache
#chown -R varnish.varnish /var/varnish_cache
#chown -R varnish.varnish /var/varnish_cache
3. 編譯/安裝Varnish
要先確認是否安裝pcre-devel 套件, 沒有的話,安裝一下吧!!
# rpm -ivh pcre-devel-6.6-2.el5_1.7.i386.rpm
#cd /usr/local/src
# tar zxvf varnish-2.1.4.tar.gz
# cd varnish-2.1.4
# ./configure --prefix=/usr/local/varnish --sysconfdir=/etc
#make && make install
4. Varnish 相關啟動檔
# cp -p redhat/varnish.initrc /etc/init.d/varnish //varnish 啟動檔
# cp -p redhat/varnish.sysconfig /etc/sysconfig/varnish //varnish 啟動檔設定檔
# cp -p redhat/varnishncsa.initrc /etc/init.d/varnishncsa //varnish ncsa格式log啟動檔
Ps. redhat/varnishlog.initrc /etc/init.d/varnishlog //varnish 2進制log啟動檔,不能用 less,more ,vi等命令開啟,需要用/usr/local/varnish/bin/varnishlog 讀取; 用法只要 –r /var/log/varnish.log 即可; 我暫時不用此二進制log方式.
# vi /etc/init.d/varnish
內容如下
exec="/usr/local/varnish/sbin/varnishd" //確認varnishd執行檔位置
ps.只要修改這一行即可, 其它使用預設就好.
存檔退出
# vi /etc/sysconfig/varnish
內容如下
DAEMON_OPTS="-a 61.64.90.169:80 \
-f /etc/varnish/default.vcl \
-T localhost:4322 \
-u varnish -g varnish \
-s file,/var/varnish_cache/cache.data,1G"
ps.只要修改這一行即可, 其它使用預設就好.
存檔退出
# chkconfig --add varnish
# chkconfig varnish on
# chkconfig varnish --list
varnish 0:off1:off2:on3:on4:on5:on6:off
5. 編輯default.vcl檔案
# vi /etc/varnish/default.vcl
# man page for details on VCL syntax and semantics.
#
# Default backend definition. Set this to point to your content
# server.
backend server1 { //第一台web server
.host = "192.168.1.254"; //主機名或ip address皆可
.probe = { //對backend web server作探針
.url = "/"; //哪個url需要varnish請求
.interval = 5s; //檢查間隔時間
.timeout = 1 s; //等待多久的探針timeout
.window = 5; // varnish將維持5個sliding window的結果
.threshold = 3; //至少有3次, .windows檢查是成功的,就宣告backends健康
}
.connect_timeout = 600s; //等待連接後端(backend)的時間
.first_byte_timeout = 600s; //等待從 backend 傳輸過來的第一個字符的時間
.between_bytes_timeout = 600s; //兩個字元的間隔時間
}
backend server2 { //第二台web server
.host = "192.168.1.246";
.probe = {
.url = "/";
.interval = 5s;
.timeout = 1 s;
.window = 5;
.threshold = 3;
}
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
}
director lb round-robin { //定義redirector loadbalance
{
.backend = server1;
}
{
.backend = server2;
}
}
acl purge {
"127.0.0.1";
"192.168.1.0";
}
sub vcl_recv {
set req.grace = 15s;
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") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) { //認證頁面不cache
return (pass);
}
if (req.http.host ~ "^(.*).catchlink.com") { //所有以*.catchlink.com的url都交由後端web server處理
set req.backend = lb; //剛定義的director
}
else {
error 404 "Unknown HostName!";
}
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not Allowed.";
return (lookup);
}
}
if (req.url ~ "\.(php|php5)($|\?)") { //.php或php? 都不cache
return (pass);
}
if (req.http.Cache-Control ~ "(no-cache|max-age=0)") {
purge_url(req.url);
}
return (lookup);
}
sub vcl_pipe {
return (pipe);
}
sub vcl_pass {
return (pass);
}
sub vcl_hash {
set req.hash += req.url;
if (req.http.host) {
set req.hash += req.http.host;
} else {
set req.hash += server.ip;
}
return (hash);
}
sub vcl_hit {
if (!obj.cacheable) {
return (pass);
}
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
return (deliver);
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
return (fetch);
}
sub vcl_fetch {
set req.grace = 10s;
if (!beresp.cacheable) {
return (pass);
}
if (!(req.url ~ "(admin|login)")) {
remove beresp.http.Set-Cookie;
}
if (req.request == "GET" && req.url ~ "\.(png|bmp|swf|txt|gif|jpg|jpeg|ico)$") {
unset req.http.cookie;
set beresp.ttl = 30d;
}
elseif (req.request == "GET" && req.url ~ "\.(html|htm|js|css)$") {
set beresp.ttl = 7d;
}
else {
set beresp.ttl = 120s;
}
return (deliver);
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
synthetic {"
<?xml version="1.0" encoding="utf-8"?> //可自行定義error 頁面
<!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>XID: "} req.xid {"</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
"};
return (deliver);
}
6. 設定Varnish log
# vi /etc/init.d/varnishncsa
內容如下
logfile="/var/log/varnishncsa.log" //log 存放位置
exec="/usr/local/varnish/bin/varnishncsa" //varnishncsa 執行檔位置
存檔退出
# chmod +x /etc/init.d/varnishncsa
# chkconfig --add varnishncsa
# chkconfig varnishncsa on
# chkconfig varnishncsa --list
varnishncsa 0:off1:off2:on3:on4:on5:on6:off
啟用Varnish log service
#service varnishncsa start
7. 設定Varnish logrotate
# vi /etc/logrotate.d/varnish
內容如下
/var/log/varnishncsa.log {
missingok
notifempty
sharedscripts
delaycompress
postrotate
/bin/kill -HUP `cat /var/run/varnishncsa.pid 2>/dev/null` 2> /dev/null || true
endscript
}
也可以自己寫shell script
#vi /usr/local/varnish_logrotate.sh
內容如下
#!/bin/sh
# This file run at 02:00
date=$(date -d ”yesterday” +”%Y-%m-%d”)
pkill -9 varnishncsa
mv /var/log/varnish.log /var/log/${date}.log
/usr/local/varnish/bin/varnishncsa -a -w /var/log/varnish.log &
gzip -c /var/log/${date}.log > /var/log/${date}.log.gz
rm -f /var/log/${date}.log
rm -f /var/log/$(date -d ”-1 month” +”%Y-%m*”).log.gz
存檔退出
#chmod +x /usr/local/varnish_logrotate.sh
#crontab –e
0 2 * * * /usr/local/ varnish_logrotate.sh //安排每天2:00執行
啟動Varnish
# service varnish start
Starting varnish HTTP accelerator: [ OK ]
# service varnish //varnish用法
Usage: /etc/init.d/varnish {start|stop|status|restart|condrestart|try-restart|reload|force-reload}
#vi /etc/rc.loacl
ulimit –SHn 51200
8. 查看listen port
# netstat -na |grep -w 80
tcp 0 0 61.64.90.169:80 0.0.0.0:* LISTEN
9. 查看varnish status
# /usr/local/varnish/bin/varnishstat
10. OS kernel tuning - 選項,可有可無
編輯 /etc/sysctl.conf
net.ipv4.ip_local_port_range = 1024 65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 3
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 3
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
#sysctl -p
沒有留言:
張貼留言