- 分布式系統架構:技術棧詳解與快速進階
- 張程
- 164字
- 2020-08-13 13:45:38
第5章
分布式架構Varnish
Varnish是一款高性能且開源的反向代理服務器和HTTP加速器,主要通過緩存來實現Web訪問加速。它基于內存進行緩存,支持精確緩存時效,性能高效。其VCL配置管理比較靈活,支持后端服務器負載和健康檢查,內部實現了負載均衡輪詢調用服務器。
本章重點內容如下:
- Varnish工作原理
- Varnish源碼編譯安裝
- Varnish配置
- Varnish核心指令
- Varnish緩存
- Varnish處理策略
- Varnish健康檢查
- Varnish優化
- Varnish高可用
5.1 Varnish工作原理
Varnish主要有兩個進程,管理進程(Management)和子進程(Child)。其中,管理進程主要負責配置變更、編譯VCL、監控運行、初始化、定期檢查子進程(子進程宕機會重新開啟);子進程包括Worker線程、Acceptor線程、Expiry線程,內部使用workspace工作區來減少多個線程間對內存的競爭。
Varnish工作模型圖如圖5-1所示。

圖5-1 Varnish工作模型圖
如圖5-1所示,Varnish的工作流程如下。
1)Varnish的某個負責接收新HTTP連接的線程開始等待用戶,如果有新的HTTP連接過來,它會負責接收,然后叫醒某個等待中的線程,并把具體的處理過程交給它。Worker線程讀入HTTP請求的URI,查找已有的object。如果命中則直接返回并回復用戶;如果沒有命中,則需要從后端服務器中讀取所請求的內容并存到緩存中,然后再回復。
2)分配緩存的過程:Varnish緩存對象時,默認會忽略體積過大的對象,因此會事先讀取對象(object)的大小,經過默認配置的驗證和篩選,保證其自身緩存策略的高效性。
為了讀寫高效性,會將篩選后合適的對象(object)壓縮,壓縮過程中會從現有的空閑存儲結構體中查找,找到最合適大小的空閑存儲塊并將object分配給它。如果空閑塊沒有用完,就用多余的內存另外組成一個空閑存儲塊,掛到管理結構體上。如果緩存已滿,就根據LRU機制,把最舊的object釋放掉。
3)釋放緩存的過程:有一個超時線程,檢測緩存中所有object的生存期,如果超出設定的TTL(Time To Live)還沒有被訪問,就刪除該object,并且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前后空閑內存塊,如果前后空閑內存和該釋放內存是連續的,就將它們合并成一塊更大的內存。
4)整個文件緩存的管理,沒有考慮文件與內存的關系,實際上認為所有的object都在內存中,如果內存不足,系統會自動將其換到swap空間,而不需要Varnish程序去控制。
5)日志:為了與系統的其他部分進行交互,Child進程使用了可以通過文件系統接口進行訪問的共享內存日志(shared memory log),因此,如果某線程需要記錄信息,其僅需要持有一個鎖,而后向共享內存中的某內存區域寫入數據,再釋放持有的鎖即可。為了減少競爭,每個worker線程都使用了日志數據緩存。
6)共享內存日志大小一般為90MB,其分為兩部分,前一部分為計數器,后一部分為客戶端請求的數據。Varnish提供了多個不同的工具,如varnishlog、varnishncsa、varnishstat等,用以來分析共享內存日志中的信息并以指定的方式進行顯示。
Varnish的優勢如下:
- Varnish支持更多的并發連接,因為Varnish的TCP連接比squid快;
- Varnish訪問速度快,因為其采用了Visual Page Cache技術,直接從內存中讀取數據;
- Varnish通過管理端口,使用正則表達式批量清除部分緩存;
- Varnish量級輕且開源。
Varnish的缺點如下:
- 進程一旦掛掉或重啟,緩存的數據將從內存中完全釋放;
- 用多臺Varnish實現負載均衡時,每次請求都會落到不同的Varnish服務器中,可能會造成URL請求穿透到后端。
5.2 Varnish源碼編譯安裝
以Centos平臺編譯環境為例,安裝Make并編譯Varnish以及相關依賴插件的方法如代碼清單5-1所示。
代碼清單5-1 編譯Varnish以及依賴插件
#需要安裝編譯gcc,已安裝忽略 yum -y install gcc automake autoconf libtool make yum install gcc gcc-c++ #安裝pcre 正規表達式,已安裝忽略 wget http:// www.programming.cn/pcre/pcre-8.36.tar.gz tar -zxvf pcre-8.36.tar.gz cd pcre-8.36 ./configure --prefix=/usr/local/pcre/ make make install #安裝libedit-dev, 已安裝忽略 yum install libedit-dev* #安裝Varnish wget -c http:// repo.varnish-cache.org/source/varnish-3.0.1.tar.gz tar xzvf varnish-3.0.1.tar.gz cd varnish-3.0.1 ./configure --prefix=/usr/local/varnish PKG_CONFIG_PATH=/usr/lib/pkgconfig make make install
在Varnish的configure命令中,--prefix=path定義一個目錄,也就是Varnish的安裝目錄,用于存放服務器上的文件。默認使用/usr/local/ varnish。
安裝成功后 /usr/local/varnish目錄如下:
bin etc include lib sbin share var
設置軟連接ln -s /usr/local/varnish/sbin/varnishd /usr/sbin/,ln -s /usr/local/varnish/bin/* /usr/local/bin/,目的是讓里面的內容暴露到外層,方便查看。
通過/usr/sbin -V查看varnish版本號,復制核心配置文件(default.vcl)到外層,如:cp /usr/local/varnish/share/doc/varnish/example.vcl /usr/local/varnish/default.vcl
啟動varnish的方法如下:
進入cd /usr/sbin/ 運行./varnished -f /usr/local/varnish/default.vcl -s malloc,32M -T 192.168.10.101:2000 -a 0.0.0.0:2222
其中,-s malloc表示存儲類型和容量,-T 192.168.10.101:2000表示指定管理IP和端口,-a 0.0.0.0:2222表示對外界提供Web服務的IP和端口。
關閉varnish的方法如下:
進入cd /usr/sbin/ 運行pkill varnished
通過Varnish代理運行的方法如下:
外部地址端口(http://192.168.10.101:2222/zachary/demo/showtime)被Varnish代理成內部地址端口(http://192.168.10.101:9021/zachary/demo/showtime),并可直接訪問Tomcat頁面。
Varnish提供了基于端口的管理方式,用戶可以通過telnet方式登錄到管理端口,對Varnish子進程進行啟動、關閉、查看狀態和清除緩存等操作,如代碼清單5-2所示。
代碼清單5-2 Varnish后臺管理
[root@varnish ~]#telnet 192.168.10.101 2000 Trying 192.168.10.101... Connected to localhost.localdomain (192.168.10.101). Escape character is '^]'. 200 154 ----------------------------- Varnish HTTP accelerator CLI. ----------------------------- Type 'help' for command list. Type 'quit' to close CLI session. #輸入"help"即可得到如下幫助信息 help 200 377 help [command] ping [timestamp] auth response quit banner status #顯示服務運行狀態 start #啟動Varnish的子服務 stop #關閉Varnish的子服務 stats #顯示服務的全部狀態 #操作VCL配置文件的相關操作,如果要修改VCL文件 vcl.load <configname> <filename> vcl.inline <configname> <quoted_VCLstring> vcl.use <configname> #載入指定的配置文件 vcl.discard <configname> #丟棄指定的VCL配置文件 vcl.list #顯示當前載入的VCL配置文件信息 vcl.show <configname> #可以顯示某個VCL文件的內容 param.show [-l] [<param>] #用于顯示程序的運行參數 param.set <param> <value> #用于動態更改某個運行參數 purge.url <regexp> #用來清除指定規則的URL緩存 purge <field> <operator> <arg> purge.list #列出執行過的規則