套句馬哥經常說的話,cache is king,在現在的企業架構中,都用到了緩存服務器,緩存,可以減輕對後端服務器的壓力,而且對於請求比較頻繁的熱區數據,我們如果緩存在緩存服務器上,都會增加被命中的概率,對於大併發的請求情況下,對於後端的服務器也是一種保護。
下面我們要介紹的是緩存服務器中的新秀,varnish,這是一款輕量級的緩存服務,相比squid,性能更高,速度更快,管理上還更加方便,被說爛的例子就是挪威最大的在線報紙,用3臺varnish替換掉了12臺squid,性能上還有提升,可見varnish的地位上升之快。
varnish於nginx有着衆多的相似之處,它們都是各自領域的新秀,而且,都是有一個master進程,多個子進程所構成,這次,我要利用varnish的緩存功能,加上haproxy的調度和高可用性,搭建一個高可用,且具有很強緩存的web服務
系統:CentOS 6.5
服務器數量:5臺
所需要的軟件及下載地址:
varnish-3.0.5-1.el6.x86_64.rpm
varnish-libs-3.0.5-1.el6.x86_64.rpm
https://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/
haproxy.x86_64 0:1.4.24-2.el6 #通過yum安裝
首先,我們先在node3、和node4這兩個主機上,提供web服務,提供主頁
node3上:
[root@node3 ~]# cat /var/www/html/index.html <h1>I am a linux lover</h1>
node4上:
[root@node4 ~]# cat /var/www/html/index.html <h1>shell is difficult to learn</h1>
然後,將這兩個web服務啓動
[root@node3 ~]# service httpd start [root@node4 ~]# service httpd start
後端的web服務已完成,下面就是搭建我們的varnish緩存服務器了
在node1和node2上都執行下列操作
[root@node1 ~]# yum install varnish-libs-3.0.5-1.el6.x86_64.rpm varnish-3.0.5-1.el6.x86_64.rpm #可以自動解決依賴關係
備份varnish的配置文件
[root@node1 ~]# cp /etc/varnish/default.vcl /etc/varnish/default.vcl.bak
編輯varnish的啓動腳本的配置文件,讓其監聽在80端口上,而且,指定存儲類型爲mallo
VARNISH_LISTEN_PORT=80 #監聽在80端口 VARNISH_STORAGE_SIZE=100M #緩存大小爲100M VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" #這裏是調用上面的變量
然後,啓動varnish服務
[root@node2 ~]# service varnish start [root@node1 ~]# ss -tlnp | grep 80 #此時,80端口已經被監聽(最好確保我們的其他web程序是關閉的) LISTEN 0 128 :::80 :::* users:(("varnishd",8840,8)) LISTEN 0 128 *:80 *:* users:(("varnishd",8840,7))
登錄到我們的varnish的控制端查看
[root@node2 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
-S:指定密鑰文件
-T:指定可以登錄的管理員的地址和端口,這個是在/etc/sysconfig/varnish文件中定義的
實驗要求:(對varnish而言)
1、要通過負載均衡的方式調度後端的兩個web服務器
2、可以在後端的web服務器的日誌文件上,查看真正訪問web服務的客戶端的IP地址
3、實現對後端兩個web服務器健康狀態的檢測
使用輪詢的調度方法
在/etc/varnish/目錄中新建一個lb.vcl的文件,作爲負載均衡作用的配置文件,配置如下
backend web1 { .host = "192.168.77.13"; .port = "80"; } backend web2 { .host = "192.168.77.14"; .port = "80"; } director webs round-robin { #使用輪詢的調度算法 {.backend = web1;} {.backend = web2;} } sub vcl_recv { set req.backend = webs; #要調用上面這個組 }
然後,我們可以通過上面的管理接口,使用這個配置文件了
varnish> vcl.load lb ./lb.vcl #加載這個配置 200 VCL compiled. #這樣就是編譯成功的提示 varnish> vcl.use lb #使用上面定義的配置 200
此時,我們在瀏覽器中測試,先訪問node1,再訪問node2
之後,無論怎麼刷新都不改變了,調出開發者工具查看
我們可以查看我們的後端web服務器的日誌文件
[root@node4 ~]# tail /var/log/httpd/access_log 192.168.77.12 – - [20/Sep/2014:20:32:28 +0800] "GET /favicon.ico HTTP/1.1" 404 288 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" 192.168.77.11 – - [20/Sep/2014:20:35:23 +0800] "GET / HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
此時,顯示的是我們的varnish服務器的地址
在後端記錄客戶端IP地址
更改配置文件,使其能夠記錄客戶端的IP地址,在上面的實驗上擴展
[root@node1 varnish]# cp lb.vcl log.vcl [root@node1 varnish]# vim log.vcl backend web1 { .host = "192.168.77.13"; .port = "80"; } backend web2 { .host = "192.168.77.14"; .port = "80"; } director webs round-robin { {.backend = web1;} {.backend = web2;} } sub vcl_recv { set req.http.X-Forwarded-For = clinet.ip; if (req.url ~ "index.html$") { return (pass); } set req.backend = webs; }
兩個web服務器都做修改
然後,將後端的web記錄日誌的格式修改如下
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
重啓httpd服務
[root@node3 ~]# service httpd restart
回到varnish服務器,加載新的配置
varnish> vcl.load log ./log.vcl 200 VCL compiled. varnish> vcl.use log 200
到瀏覽器中,分別訪問
發現,網頁發生了變化,這是緩存時間結束了,新的請求返回新的網頁,之後,連續刷新時,就不會緩存了
查看我們後端web服務器的日誌文件
[root@node3 ~]# tail /var/log/httpd/access_log 192.168.77.11 – - [20/Sep/2014:20:35:24 +0800] "GET /favicon.ico HTTP/1.1" 404 288 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" [root@node4 ~]# tail /var/log/httpd/access_log 192.168.77.1, 192.168.77.1 – - [20/Sep/2014:20:54:51 +0800] "GET / HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
此時,上面記錄的都是當前windows主機的地址了,如果沒有,可以多次刷新網頁後查看,可能還是緩存命中
健康檢查機制:
如果,我們的後端web宕機了呢?我們是否發覺?下面引入健康檢查機制
[root@node1 varnish]# cp log.vcl health.vcl [root@node1 varnish]# vim health.vcl probe healthchk { #定義一個健康檢測的標準 .url = "/"; .interval = 5s; .timeout = 2s; } backend web1 { .host = "192.168.77.13"; .port = "80"; .probe = healthchk; #調用健康檢測 } backend web2 { .host = "192.168.77.14"; .port = "80"; .probe = healthchk; } director webs round-robin { {.backend = web1;} {.backend = web2;} } sub vcl_recv { set req.http.X-Forwarded-For = client.ip; if (req.url ~ "index.html$") { return (pass); } set req.backend = webs; }
加載新的配置,並使用
varnish> vcl.load health ./health.vcl 200 VCL compiled. varnish> vcl.use health 200
此時,我們可以將後端的兩個web服務器的http服務都停掉
[root@node4 ~]# service httpd stop
在我們的瀏覽器中查看
此時,健康狀態就顯示出來了,不過,你可能要等緩存失效後,才能刷出這個網頁
最後,我們可以在前端加上一個haproxy,作爲這兩個varnish緩存服務器的負載均衡器
安裝haproxy,這裏使用yum的方式
[root@hap ~]# yum install -y haproxy
備份配置文件,並且對配置文件進行編輯
[root@hap ~]# cd /etc/haproxy/ [root@hap haproxy]# cp haproxy.cfg haproxy.cfg.bak [root@hap haproxy]# vim haproxy.cfg frontend main *:80 maxconn 3000 default_backend webs backend webs balance uri server varnish1 192.168.77.11 check port 80 server varnish2 192.168.77.12 check port 80 server back 127.0.0.1:8080 backup stats enable #開啓status功能 stats admin if TRUE #開啓管理功能 stats hide-version #隱藏版本號 stats scope . #當前作用域 stats uri /admin?stas #自定義uri stats realm admin\ authorizen #用戶認證模式 stats auth hapadmin:varnish #認證的用戶名和密碼
然後,啓動haproxy服務
[root@hap haproxy]# service haproxy start [root@hap haproxy]# ss -tlnp | grep 80 #此時,已經監聽80端口 LISTEN 0 128 *:80 *:* users:(("haproxy",2497,4))
將後端的兩個web服務啓動,然後,在瀏覽器中訪問
此時,還可以查看我們的status狀態頁
此時,我們還可以提供sorry server,即這裏的back,在haproxy的本機上
[root@hap haproxy]# cat /var/www/html/index.html <h1>Sorry! please wait!</h1>
同時,還得修改httpd的配置文件,使其監聽在8080端口上,因爲80被haproxy佔用
[root@hap haproxy]# vim /etc/httpd/conf/httpd.conf Listen 8080 #修改此項 並且,把http服務啓動 [root@hap haproxy]# service httpd start
我們可以在stats頁面上,讓後端的兩個varnish服務器停止工作,刷瀏覽器
訪問我們的站點
當後端主機宕機後,我們的haproxy上的sorry server就能派的上用場了,詳細的varnish的內容會在近期的varnish原理知識中發佈出來,這也是自己的任務。