複製鏈接
請複製以下鏈接發送給好友

Varnish

鎖定
Varnish是一款高性能的開源HTTP加速器挪威最大的在線報紙 Verdens Gang 使用3台Varnish代替了原來的12台Squid,性能比以前更好。 [1] 
中文名
Varnis
作    者
Poul-Henning Kamp
Accept 線程
接受請求
Work 線程
多個

Varnish簡介

Varnish 的作者Poul-Henning Kamp是FreeBSD的內核開發者之一,他認為現在的計算機比起1975年已經複雜許多。在1975年時,儲存媒介只有兩種:內存與硬盤。但現在計算機系統的內存除了主存外,還包括了CPU內的L1、L2,甚至有L3快取。硬盤上也有自己的快取裝置,因此Squid Cache自行處理物件替換的架構不可能得知這些情況而做到最佳化,但操作系統可以得知這些情況,所以這部份的工作應該交給操作系統處理,這就是 Varnish cache設計架構。 [1] 
varnish項目是2006年發佈的第一個版本0.9.距今已經有十多年了,此文檔之前也提過varnish還不穩定,那是2007年時候編寫的,經過varnish開發團隊和網友們的辛苦耕耘,現在的varnish已經很健壯。很多門户網站已經部署了varnish,並且反應都很好,甚至反應比squid還穩定,且效率更高,資源佔用更少。相信在反向代理,web加速方面,varnish已經有足夠能力代替squid。

Varnish總體架構

2.1 總體流程
主進程 fork 子進程,主進程等待子進程的信號,子進程退出後,主進程重新啓動子進程
子進程生成若干線程
Accept 線程:接受請求,將請求掛在 overflow隊列上
Work 線程: 多個,從對列上摘除請求,對請求進行處理,直到完成,然後處理下一個
請求
Epoll 線程: 一個請求處理稱作一個 session,在 session 週期內,處理完請求後,會交給
Epoll 處理,監聽是否還有事件發生。
Expire 線程:對於緩存的對象,根據過期時間,組織成二叉堆,該線程週期檢查該堆的
根,處理過期的文件。
線程之間的關係:
2.1.1 accept 線程
監聽端口,接受連接。
接受後組織成 struct ses(session 結構) ,看是否有空閒的工作線程,如果有,將請求給它,
pthread_cond_signal 信號通知它沒有空閒線程,如果 overflow過大,則放棄該請求。否則,
將其掛在 overflow 上(需要更多工作線程,發通知)。
繼續監聽 2.1.2 work 線程
從 overflow隊列上摘取請求(struct ses),進入狀態機處理,處理結束後,通過 pipe通信,
將 struct ses發送給 epoll 線程。
2.1.3 Epoll 線程,得到傳過來的 struct ses,若還沒有過期,將 socket 放入 epoll 的事件中,事
件發生時,也會將其放入到 overflow中進行。

Varnish工作流程

Varnish與一般服務器軟件類似,分為master(management)進程和child(worker,主要做cache的工作)進程。master進程讀入命令,進行一些初始化,然後fork並監控child進程。child進程分配若干線程進行工作,主要包括一些管理線程和很多woker線程。
針對文件緩存部分,master讀入存儲配置(-s file[,path[,size[,granularity]]] ),調用合適的存儲類型,然後創建/讀入相應大小的緩存大文件。接着,master初始化管理該存儲空間的結構體。這些變量都是全局變量,在fork以後會被child進程所繼承(包括文件描述符)。
在child進程主線程初始化過程中,將前面打開的存儲大文件整個mmap到內存中(如果超出系統的虛擬內存,mmap失敗,進程會減少原來的配置mmap大小,然後繼續mmap),此時創建並初始化空閒存儲結構體,掛到存儲管理結構體,以待分配。
接着,真正的工作開始,Varnish的某個負責接受新HTTP連接的線程開始等待用户,如果有新的HTTP連接過來,它總負責接收,然後叫醒某個等待中的線程,並把具體的處理過程交給它。Worker線程讀入HTTP請求的URI,查找已有的object,如果命中則直接返回並回複用户。如果沒有命中,則需要將所請求的內容,從後端服務器中取過來,存到緩存中,然後再回復。
分配緩存的過程是這樣的:它根據所讀到object的大小,創建相應大小的緩存文件。為了讀寫方便,程序會把每個object的大小變為最接近其大小的內存頁面倍數。然後從現有的空閒存儲結構體中查找,找到最合適的大小的空閒存儲塊,分配給它。如果空閒塊沒有用完,就把多餘的內存另外組成一個空閒存儲塊,掛到管理結構體上。如果緩存已滿,就根據LRU機制,把最舊的object釋放掉。
釋放緩存的過程是這樣的:有一個超時線程,檢測緩存中所有object的生存期,如果超出設定的TTL(Time To Live)沒有被訪問,就刪除之,並且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前面或後面的空閒內存塊,如果前面或後面的空閒內存和該釋放內存是連續的,就將它們合併成更大一塊內存。
整個文件緩存的管理,沒有考慮文件與內存的關係,實際上是將所有的object都考慮是在內存中,如果系統內存不足,系統會自動將其換到swap空間,而不需要varnish程序去控制。

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
make
make install
groupadd varnish
useradd -d /var/lib/varnish -g varnish -s /sbin/nologin varnish
ln -s /usr/local/varnish/sbin/varnishd /usr/sbin/varnishd
啓動varnish:
varnishd -f /usr/local/varnish/etc/varnish/default.vcl -s malloc,1G -g varnish -u varnish -T 127.0.0.1:2000
關閉varnish:
pkill varnish
啓動參數介紹:
-f /usr/local/etc/varnish/default.vcl
這個 –f 選項指定varnishd使用哪個配置文件。
-s malloc,1G
這個 –s 選項用來確定varnish使用的存儲類型和存儲容量,我使用的是malloc類型(malloc是一個C函數,用於分配內存空間), 1G 定義多少內存被malloced,1G = 1gigabyte。
-T 127.0.0.1:2000
Varnish有一個基於文本的管理接口,啓動它的話可以在不停止varnish的情況下來管理varnish。您可以指定管理軟件監聽哪個接口。當然您不能讓全世界的人都能訪問您的varnish管理接口,因為他們可以很輕鬆的通過訪問varnish管理接口來獲得您的root訪問權限。我推薦只讓它監聽本機端口。如果您的系統裏有您不完全信任的用户,您可以通過防火牆規則來限制他訪問varnish的管理端口。
-a 0.0.0.0:8080
這一句的意思是制定varnish監聽所有IP發給8080端口的http請求,如果在生產環境下,您應該讓varnish監聽80,這也是默認的。
vcl配置文件的介紹請執行如何命令查看:
man /usr/local/varnish/share/man/man7/vcl.7

Varnish版本發佈

2011年08月24日,Varnish 3.0.1 RC1 發佈,HTTP加速器。 [2] 
2011年08月30日,Varnish 3.0.1 正式版發佈了,與 3.0 版本比較,改進包括:
對象以優雅和保持設置被錯誤地視為候選的短暫存儲,但不會迅速清理,這表現為如果有一個內存泄漏。現在這是固定的。
當多個客户正在等待一個對象,所有客户端會醒來當一個物體變得可用,從而導致卡線程。這已經被修正
一個bug在XML實體是如何處理應急服務國際公司已經固定
文檔目睹了大量的更新
varnishncsa現在更加穩定和支持顯示任意請求和響應字段。 [3] 
2011年10月26日,Varnish Cache 3.0.2 發佈。 [4] 
2012年08月20日,Varnish Cache 3.0.3 發佈。
2013年06月17日,Varnish Cache 3.0.4 發佈,為目前最新版本。
***
最新版為2018-04-15更新,地址於參考資料。 [5] 
參考資料