1、傳統緩存之一(404)
這個方法是把nginx的404錯誤導向到後端,然後用proxy_store把後端回傳的頁面儲存。
配置:
location / {
root /home/html/;#主目錄
expires 1d;#網頁的過期時間
error_page 404 =200 /fetch$request_uri;#404定向到/fetch目錄下
}
location /fetch/ {#404定向到這裡
internal;#指明這個目錄不能在外部直接存取到
expires 1d;#網頁的過期時間
alias /home/html/;#虛擬目錄檔案系統位址要和locaion /一致,proxy_store會將檔案儲存到這個目錄下
proxy_pass http://www.sudone.com/;#後端upstream位址,/fetch同時是一個代理
proxy_set_header Accept-Encoding '';#讓後端不要回傳壓縮( gzip或deflate)的內容,儲存壓縮後的內容會引發亂子。
proxy_store on;#指定nginx將代理傳回的檔案保存
proxy_temp_path /home/tmp;#暫存目錄,這個目錄要和/home/html在同一個硬碟分割區內
}
使用的時候還有要注意是nginx要有權限往/home/tmp和/home/html下有寫入檔案的權限,在linux下nginx一般會配置成nobody用戶運行,這樣這兩個目錄就要chown nobody,設成nobody用戶專用,當然也可以chmod 777,不過所有有經驗的系統管理員都會建議不要隨便使用777。
2、傳統緩存之二(!-e)
原理和404跳轉基本上一致,但更簡潔一些:
location / {
root /home/html/;
proxy_store on;
proxy_set_header Accept-Encoding '';
proxy_temp_path /home/tmp;
if ( !-f $request_filename )
{
proxy_pass http://www.sudone.com/;
}
}
可以看到這個設定比404節約了不少程式碼,它是用!-f來判斷請求的檔案在檔案系統上存不存在,不存在就proxy_pass到後端,回傳同樣是用proxy_store儲存。
兩種傳統快取都有著基本一樣的優點和缺點:
缺點1:不支援帶參數的動態鏈接,例如read.php?id=1,因為nginx只保存檔名,所以這個連結只在檔案系統下儲存為read.php,這樣使用者存取read.php?id= 2時會回傳不正確的結果。同時不支援http://www.sudone.com/這種形式的首頁和二級目錄http://www.sudone.com/download/,因為nginx非常老實,會將這樣的請求照連結寫入文件系統,而這個連結顯然是一個目錄,所以保存失敗。這些情況都需要寫rewrite才能正確保存。
缺點2:nginx內部沒有快取過期和清理的任何機制,這些快取的檔案會永久地保存在機器上,如果要快取的東西非常多,那就會撐暴整個硬碟空間。為此可以使用一個shell腳本定期清理,同時可以撰寫php等動態程式來做即時更新。
缺點3:只能快取200狀態碼,因此後端回傳301/302/404等狀態碼都不會緩存,假如剛好有一個訪問量很大的偽靜態連結被刪除,那就會不停穿透導致後端承載不小壓力。
缺點4:nginx不會自動選擇內存或硬碟作為儲存介質,一切由配置決定,當然在當前的作業系統裡都會有作業系統級的檔案快取機制,所以存在硬碟上也不需要過分擔心大並發讀取造成的io性能問題。
nginx傳統快取的缺點也是它和squid等快取軟體的不同之特色,所以也可以看作其優點。在生產應用中它常常用作和squid的搭檔,squid對於帶?的鏈接往往無法阻擋,而nginx能將其訪問攔住,例如:http://sudone.com/?和http://sudone.com /在squid上會被當做兩個鏈接,所以會造成兩次穿透;而nginx只會保存一次,無論鏈接變成http://sudone.com/?1還是http://sudone.com/? 123,均不能透過nginx緩存,從而有效地保護了後端主機。
nginx會非常老實地將鏈接形式保存到文件系統中,這樣對於一個鏈接,可以很方便地查閱它在緩存機器上的緩存狀態和內容,也可以很方便地和別的文件管理器如rsync等配合使用,它完完全全就是一個檔案系統結構。
這兩種傳統快取都可以在linux下將檔案儲存到/dev/shm裡,一般我也是這麼做的,這樣可以利用系統記憶體來做緩存,利用記憶體的話,清理過期內容速度就會快得多。使用/dev/shm/時除了要把tmp目錄也指向到/dev/shm這個分區外,如果有大量小檔案和目錄,還要修改一下這個記憶體分區的inode數量和最大容量:
mount -o size=2500M -o nr_inodes=480000 -o noatime,nodiratime -o remount /dev/shm
上面的命令在一台有3G內存的機器上使用,因為/dev/shm默認最大內存是系統內存的一半就是1500M,這條命令將其調大成2500M,同時shm系統inode數量默認情況下可能是不夠用的,但有趣的是它可以隨意調節,這裡調節為480000保守了點,但也基本上夠用了。
3.基於mem cache d的緩存
nginx對memcached有所支持,但功能並不是特別之強,性能上還是非常優秀。
location /mem/ {
if ( $uri ~ "^/mem/([0-9A-Za-z_]*)$" )
{
set $memcached_key "$1";
memcached_pass 192.168.1.2:11211;
}
expires 70;
}
這個配置會將http://sudone.com/mem/abc指明到memcached的abc這個key去取資料。
nginx目前沒有寫入memcached的任何機制,所以要往memcached裡寫入資料得用後台的動態語言完成,可以利用404定向到後端去寫入資料。
4.基於第三方插件ncache
ncache是新浪兄弟開發的一個不錯的項目,它利用nginx和memcached實現了一部分類似squid快取的功能,我並沒有使用這個插件的經驗,可以參考:
http://code.google.com/p/ncache/
5.nginx新開發的proxy_cache功能
從nginx-0.7.44版開始,nginx支援了類似squid較為正規的cache功能,目前還處於開發階段,支援相當有限,這個快取是把鏈接用md5編碼hash後保存,所以它可以支援任意鏈接,同時也支援404/301/302這樣的非200狀態。
配置:
首先設定一個cache空間:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=NAME:10m inactive=5m max_size=2m clean_time=1m;
注意這個配置是在server標籤外,levels指定該快取空間有兩層hash目錄,第一層目錄是1個字母,第二層為2個字母,保存的檔案名稱就會類似/path/to/cache /c/29/b7f54b2df7773722d382f4809d65029c;keys_zone為這個空間取個名字,10m指空間大小為10MB;inactive的5m指快取預設時長5分鐘;max_size的2m是指單一檔案超過2mtime清理一次快取。
location / {
proxy_pass http://www.sudone.com/;
proxy_cache NAME;#使用NAME這個keys_zone
proxy_cache_valid 200 302 1h;#200和302狀態碼保存1小時
proxy_cache_valid 301 1d;#301狀態碼保存一天
proxy_cache_valid any 1m;#其它的保存一分鐘
}