一、varnishd指令
Varnish啟動的命令是/usr/local/varnish/sbin/varnishd,此命令參數較多,用法比較復雜,在命令行執行“/usr/local/varnish/sbin/varnishd –h”即可得到varnishd的詳細用法,表2-6列出了varnishd常用參數的使用方法和含義。
表1
- 命令參數 參數含義
- -a address:port 表示varnish對httpd的監聽地址及其端口
- -b address:port 表示后端服務器地址及其端口
- -d 表示使用debug調試模式
- -f file 指定varnish服務器的配置文件
- -p param=value 指定服務器參數,用來優化varnish性能
- -P file Varnish進程PID文件存放路徑
- -n dir 指定varnish的工作目錄
- -s kind[,storageoptions] 指定varnish緩存內容的存放方式,常用的方式有:“-s file,<dir_or_file>,<size>”。
- 其中“<dir_or_file>”指定緩存文件的存放路徑,“<size>”指定緩存文件的大小
- -t 指定缺省的TTL值
- -T address:port 設定varnish的telnet管理地址及其端口
- -w int[,int[,int]] 設定varnish的工作線程數,常用的方式有:
- -w min,max
- -w min,max,timeout
- 例如:-w5,51200,30,這里需要說明下,在varnish2.0版本以后,最小啟動的線程數不能設定過大,設置過大,會導致varnish運行異常緩慢。
-V 顯示varnish版本號和版權信息
二、 配置varnish運行腳本
在安裝varnish一節中,已經將varnish的管理腳本拷貝到了相應的目錄下,這里稍作修改即可使用,首先修改/etc/sysconfig/varnish文件,根據本章的實例,配置好的文件如下:
- NFILES=131072
- MEMLOCK=82000
- DAEMON_OPTS="-a 192.168.12.246:80 \
- -T 127.0.0.1:3500 \
- -f /usr/local/varnish/etc/vcl.conf \
- -u varnish -g varnish \
- -w 2,51200,10 \
- -n /data/varnish/cache \
- -s file, /data/varnish/cache/varnish_cache.data,4G"
這里需要說明的是,緩存文件“varnish_cache.data”在32位操作系統下,最大僅能支持2G,如果需要更大緩存文件則需要安裝64為Linux操作系統。
接着需要修改的文件是/etc/init.d/varnish,找到如下行,改為相應的路徑即可:
- exec="/usr/local/varnish/sbin/varnishd"
- prog="varnishd"
- config="/etc/sysconfig/varnish"
- lockfile="/var/lock/subsys/varnish"
其中,“exec”用於指定varnishd的路徑,只需修改為varnish安裝路徑下對應的varnishd文件即可。“config”用於指定varnish守護進程配置文件路徑。
兩個文件修改完畢,就可以授權、運行/etc/init.d/varnish腳本了,執行如下:
- [root@varnish-server ~]#chmod 755 /etc/init.d/varnish
- [root@varnish-server ~]#/etc/init.d/varnish
- Usage:/etc/init.d/varnish
- {start|stop|status|restart|condrestart|try-restart|reload|force-reload}
從輸出可知,此腳本功能強大,可以對varnish進行啟動、關閉、查看狀態、重啟等操作。最后,啟動varnish:
- [root@varnish-server ~]# /etc/init.d/varnish start
- Starting varnish HTTP accelerator: [ OK ]
三、管理varnish運行日志
varnish是通過內存共享的方式提供日志的,它提供了兩種日志輸出形式,分別是:
通過自帶的varnishlog指令可以獲得varnish詳細的系統運行日志。
例如:
- [root@varnish-server ~]#/usr/local/varnish/bin/varnishlog -n /data/varnish/cache
- 0 CLI - Rd ping
- 0 CLI - Wr 200 PONG 1279032175 1.0
- 0 CLI - Rd ping
- 0 CLI - Wr 200 PONG 1279032178 1.0
通過自帶的varnishncsa指令得到類似apache的combined輸出格式的日志。
例如:
- [root@varnish-server ~]#/usr/local/varnish/bin/varnishncsa -n /data/varnish/cache
也可以將日志輸出到一個文件中,通過“-w”參數指定即可:
- [root@varnish-server ~]#/usr/local/varnish/bin/varnishncsa -n /data/varnish/cache \
- >-w /data/varnish/log/varnish.log
varnish兩種日志輸出形式中,第一種在大多數情況下並不是必須的,這里重點介紹下第二種日志輸出形式的配置方式。
下面編寫一個名為varnishncsa的shell腳本,並把此文件放到/etc/init.d目錄下,varnishncsa腳本的完整內容如下所示:
- #!/bin/sh
- if [ "$1" = "start" ];then
- /usr/local/varnish/bin/varnishncsa -n /data/varnish/cache -f |/usr/sbin/rotatelogs /data/varnish/log/varnish.%Y.%m.%d.%H.log 3600 480 &
- elif [ "$1" = "stop" ];then
- killall varnishncsa
- else
- echo $0 "{start|stop}"
- fi
在這個腳本中,通過管道方式把日志導入到“rotatelogs”中,而rotatelogs是一個文件分割工具,它可以通過指定時間或者大小等方式來分割日志文件,這樣就避免了日志文件過大造成的性能問題。
其中,“3600”是一個小時,也就是每個小時生成一個日志文件,“480”是一個時區參數,中國是第八時區,相對於UTC相差480分鍾,如果不設置480這個參數,將導致日志記錄時間和服務器時間相差8小時。關於rotatelogs命令用法,這里不再詳細講述。
通過對varnish日志的監控,可以知道varnish的運行狀態和情況。
接着,將此腳本進行授權:
- [root@varnish-server ~]#chmod 755 /etc/init.d/varnishncsa
最后就可以通過如下方式,進行啟動、關閉日志等操作了:
- [root@varnish-server ~]#/etc/init.d/varnishncsa {start|stop }
四、管理Varnish
1、查看varnish進程
通過上面章節的講解,varnish已經可以啟動起來了,執行如下命令可以查看varnish是否正常啟動:
- [root@varnish-server ~]# ps -ef|grep varnish
- root 29615 1 0 00:20 pts/1 00:00:00 /usr/local/varnish/bin/varnishncsa -n /data/varnish/cache -f
- root 29616 1 0 00:20 pts/1 00:00:00 /usr/sbin/rotatelogs /data/varnish/log/varnish.%Y.%m.%d.%H.log 3600 480
- root 29646 1 0 00:21 ? 00:00:00 /usr/local/varnish/sbin/varnishd -P /var/run/varnish.pid -a 192.168.12.246:80 -T 127.0.0.1:3500 -f /usr/local/varnish/etc/vcl.conf -u varnish -g varnish -w 2,51200,10 -n /data/varnish/cache -s file,/data/varnish/cache/varnish_cache.data,4G
- varnish 29647 29646 0 00:21 ? 00:00:00 /usr/local/varnish/sbin/varnishd -P /var/run/varnish.pid -a 192.168.12.246:80 -T 127.0.0.1:3500 -f /usr/local/varnish/etc/vcl.conf -u varnish -g varnish -w 2,51200,10 -n /data/varnish/cache -s file,/data/varnish/cache/varnish_cache.data,4G
從命令執行結果可知,PID為29615和29616的進程是varnish的日志輸出進程,而PID為29646的進程是varnishd的主進程,並且派生出了一個PID為29647的子進程。這點跟apache類似。
如果varnish正常啟動的話,80端口和3500端口應該處於監聽狀態,通過如下命令可以查看:
- [root@varnish-server ~]# netstat -antl|grep 3500
- tcp 0 0 127.0.0.1:3500 0.0.0.0:* LISTEN
- [root@varnish-server ~]#netstat -antl|grep 80
- tcp 0 0 192.168.12.246:80 0.0.0.0:* LISTEN
- tcp 1 0 192.168.12.246:41782 192.168.12.26:80 CLOSE_WAIT
其中,80端口為varnish的代理端口,3500為varnish的管理端口。
2、查看varnish緩存效果與狀態
可以通過瀏覽器訪問對應的網頁,查看varnish緩存的效果,如果varnish緩存成功的話,第二次打開網頁的速度會明顯比第一次快,但是這種方式並不能夠完全說明問題,下面通過命令行方式,通過查看網頁頭來查看命中情況,操作如下:
- [root@varnish-server ~]# curl -I http://www.ixdba.net/a/mz/2010/0421/11.html
- HTTP/1.1 200 OK
- Server: Apache/2.2.14 (Unix) PHP/5.3.1 mod_perl/2.0.4 Perl/v5.10.1
- Last-Modified: Sat, 10 Jul 2010 11:25:15 GMT
- ETag: "5e850b-616d-48b06c6031cc0"
- Content-Type: text/html
- Content-Length: 24941
- Date: Fri, 09 Jul 2010 08:29:16 GMT
- X-Varnish: 1364285597
- Age: 0
- Via: 1.1 varnish
- Connection: keep-alive
- X-Cache: MISS from www.ixdba.net
#這里的"MISS"表示此次訪問沒有從緩存讀取。
再次打開這個頁面,查看網頁頭信息:
- [root@varnish-server ~]# curl -I http://www.ixdba.net/a/mz/2010/0421/11.html
- HTTP/1.1 200 OK
- Server: Apache/2.2.14 (Unix) PHP/5.3.1 mod_perl/2.0.4 Perl/v5.10.1
- Last-Modified: Sat, 10 Jul 2010 11:25:15 GMT
- ETag: "5e850b-616d-48b06c6031cc0"
- Content-Type: text/html
- Content-Length: 24941
- Date: Fri, 09 Jul 2010 08:30:35 GMT
- X-Varnish: 1364398612 1364285597
- Age: 79
- Via: 1.1 varnish
- Connection: keep-alive
- X-Cache: HIT from www.ixdba.net
#由“HIT”可知,第二次訪問此頁面時,是從緩存中讀取內容了,也就是緩存命中。
緩存命中率的高低直接說明了varnish的運行狀態和效果,較高的緩存命中率說明了varnish運行狀態良好,web服務器的性能也會提高很多,反之,過低的緩存命中率說明varnish的配置可能存在問題,那么就需要進行調整,因此,從整體上了解varnish的命中率和緩存狀態,對於優化和調整varnish至關重要。
varnish提供了一個varnishstat命令,通過它可以幫我們獲得很多重要的信息。
下面是一個varnish系統的緩存狀態:
- [root@varnish-server ~]#/usr/local/varnish/bin/varnishstat -n /data/varnish/cache
- Hitrate ratio: 10 100 113
- Hitrate avg: 0.9999 0.9964 0.9964
- 9990 68.92 49.70 Client connections accepted
- 121820 953.84 606.07 Client requests received
- 112801 919.88 561.20 Cache hits
- 68 0.00 0.34 Cache misses
- 2688 33.96 13.37 Backend conn. success
- 6336 1.00 31.52 Backend conn. reuses
- 2642 33.96 13.14 Backend conn. was closed
- 8978 29.96 44.67 Backend conn. recycles
- 6389 1.00 31.79 Fetch with Length
- 2630 32.96 13.08 Fetch chunked
- 444 . . N struct sess_mem
- 23 . . N struct sess
- 64 . . N struct object
- 78 . . N struct objectcore
- 78 . . N struct objecthead
- 132 . . N struct smf
- 2 . . N small free smf
- 3 . . N large free smf
- 6 . . N struct vbe_conn
- 14 . . N worker threads
- 68 1.00 0.34 N worker threads created
- 0 0.00 0.00 N queued work requests
- 1201 11.99 5.98 N overflowed work requests
- 1 . . N backends
- 4 . . N expired objects
- 3701 . . N LRU moved objects
- 118109 942.85 587.61 Objects sent with write
- 9985 71.91 49.68 Total Sessions
- 121820 953.84 606.07 Total Requests
這里需要注意的幾個地方是:
“Client connections accepted”表示客戶端向反向代理服務器成功發送HTTP請求的總數量。
"Client requests received"表示到現在為止,瀏覽器向反向代理服務器發送HTTP請求的累積次數,由於可能會使用長連接,所以這個值一般會大於“Client connections accepted”。
“Cache hits”表示反向代理服務器在緩存區中查找並且命中緩存的次數。
“Cache misses”表示直接訪問后端主機的請求數量,也就是非命中數。
“N struct object”表示當前被緩存的數量。
“N expired objects”表示過期的緩存內容數量。
“N LRU moved objects”表示被淘汰的緩存內容個數。
五、管理varnish緩存內容
Varnish的一個顯著優點是可以靈活的管理緩存內容,而管理緩存主要的工作是如何迅速有效的控制和清除指定的緩存內容,varnish清除緩存相對比較復雜,不過幸運的是,可以通過varnish的管理端口發送PURGE指令來清除不需要的緩存。
下面列出了清除緩存內容的命令格式:
/usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.url <regexp>
下面的命令可以列出最近清除的詳細URL列表:
/usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.list
舉例如下:
(1)如果要清除http://www.example.com/a/2010.html的URL地址,可以執行如下命令:
/usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.url /a/2010.html
(2)批量清除類似http://www.example.com/a/b/s*.html的URL地址,可執行如下命令:
/usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.url ^/a/b/s.*$
(3)批量清除類似http://www.example.com/a/b/*.html的URL地址,可執行如下命令:
/usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.url ^/a/b.*$
(4)如果要清除所有緩存,可執行如下命令:
/usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.url ^.*$
(5)查看最近清除的詳細URL列表
[root@varnish-server ~]# /usr/local/varnish/bin/varnishadm -T 192.168.12.246:3500 purge.list
0x2dc310c0 1278674980.497631 0 req.url ~ /zm/a/web/2010/0423/64.html
0x2dc31100 1278674964.851327 1 req.url ~ ^/zm/a/d.*$
除了通過linux命令行方式清理varnish緩存外,還可以通過telnet到管理端口的方式來清理緩存頁面,例如:
- [root@varnish-server ~]#telnet 192.168.12.246 3500
- Trying 192.168.12.246...
- Connected to localhost.localdomain (192.168.12.246).
- Escape character is '^]'.
- 200 154
- -----------------------------
- Varnish HTTP accelerator CLI.
- -----------------------------
- Type 'help' for command list.
- Type 'quit' to close CLI session.
- purge.url /a/mz/2010/0421/11.html #這里是清除這個頁面緩存
- 200 0
- purge.url ^/zm/a/d.*$ #這里是清除/zm/a/d/目錄下所有以字母d開頭的緩存頁面
- 200 0
對於系統管理人員或者運維人員來說,時刻了解varnish命中率是至關重要的,雖然varnish給出了很詳細的統計數據,但是統計的數據不是很直觀,並且必須登錄到varnish服務器才能查看,下面給出一個php程序,可以隨時隨地,並且非常清晰的了解varnish系統的命中率相關情況,程序如下:
- <?php
- // This is just a code snippet written by Jason "Foxdie" Gaunt, its not meant to be executed, it may work as-is, it may not.
- // I freely acknowledge this code is unoptimised but it has worked in practice for 6 months :)
- // Lets define our connection details
- $adminHost = "127.0.0.1"; // varnish服務器的IP地址
- $adminPort = "3500"; // varnish服務器管理端口
- // pollServer(str) - this function connects to the management port, sends the command and returns the results, or an error on failure
- function pollServer($command) {
- global $adminHost, $adminPort;
- $socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname("tcp"));
- if ((!socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, Array("sec" => "5", "usec" => "0"))) OR (!socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, Array("sec" => "5", "usec" => "0")))) {
- die("Unable to set socket timeout");
- }
- if (@socket_connect($socket, $adminHost, $adminPort)) {
- $data = "";
- if (!$socket) {
- die("Unable to open socket to " . $server . ":" . $port . "\n");
- }
- socket_write($socket, $command . "\n");
- socket_recv($socket, $buffer, 65536, 0);
- $data .= $buffer;
- socket_close($socket);
- return $data;
- }
- else {
- return "Unable to connect: " . socket_strerror(socket_last_error()) . "\n";
- }
- }
- // byteReduce(str) - this function converts a numeric value of bytes to a human readable format and returns the result
- function byteReduce($bytes) {
- // Terabytes
- if ($bytes > 1099511627776) {
- return round($bytes / 1099511627776) . "TB";
- }
- else if ($bytes > 1073741824) {
- return round($bytes / 1073741824) . "GB";
- }
- else if ($bytes > 1048576) {
- return round($bytes / 1048576) . "MB";
- }
- else if ($bytes > 1024) {
- return round($bytes / 1024) . "KB";
- }
- else {
- return $bytes . "B";
- }
- }
- // This is where our main code starts
- echo "<div class=\"inner\"><br />Statistics since last reset:<ul>";
- $stats = pollServer("stats");
- if (substr($stats, 0, 3) == "200") { // If request was legitimate
- // Clear all excessive white space and split by lines
- $stats = preg_replace("/ {2,}/", "|", $stats);
- $stats = preg_replace("/\n\|/", "\n", $stats);
- $statsArray = explode("\n", $stats);
- // Removes the first call return value and splits by pipe
- array_shift($statsArray);
- $statistics = array();
- foreach ($statsArray as $stat) {
- @$statVal = explode("|", $stat);
- @$statistics[$statVal[1]] = $statVal[0];
- }
- unset($stats, $statsArray, $stat, $statVal);
- // Start outputting statistics
- echo "<li>" . $statistics["Client connections accepted"] . " clients served over " . $statistics["Client requests received"] . " requests";
- echo "<li>" . round(($statistics["Cache hits"] / $statistics["Client requests received"]) * 100) . "% of requests served from cache";
- echo "<li>" . byteReduce($statistics["Total header bytes"] + $statistics["Total body bytes"]) . " served (" . byteReduce($statistics["Total header bytes"]) . " headers, " . byteReduce($statistics["Total body bytes"]) . " content)";
- // The following line is commented out because it only works when using file storage, I switched to malloc and this broke
- // echo "<li>" . byteReduce($statistics["bytes allocated"]) . " out of " . byteReduce($statistics["bytes allocated"] + $statistics["bytes free"]) . " used (" . round(($statistics["bytes allocated"] / ($statistics["bytes allocated"] + $statistics["bytes free"])) * 100) . "% usage)";
- }
- else {
- echo "Unable to get stats, error was: \"" . $stats;
- }
- echo "</ul></div>";
- ?>
將此php程序放到varnish服務器上,即可統計處當前varnish的命中率以及緩存狀態,統計結果類似於下面的一個輸出:
- Statistics since last reset:
- 63543 clients served over 584435 requests
- 98% of requests served from cache
- 4GB served (246MB headers, 4GB content)
在這個輸出中,清晰的列出了瀏覽器請求總數、緩存命中率、緩存區中所有緩存內容的HTTP頭信息長度和緩存內容的正文長度。根據這個結果判斷,varnish的緩存效果還是很不錯的,命中率很高。