Thursday, March 29, 2012

Varnish – 安裝

架構



client user 有一的web request, 會先經由cache server查看該要求資料是否有在自已cache 暫存裡面, 如果有則直接回應給client user, 反之則向後端web server要求資料然後自已回存一份,然後再回應給client user. 這裡varnish cache server 將扮演前端loadbalancereverse 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

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將維持5sliding 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.comurl都交由後端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)($|\?)") {   //.phpphp? 都不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
#sysctl -p

                  http://www.varnish-cache.org/docs/2.1/
HomeAny source

No comments:

Post a Comment