nginx緩存cache的方案

1. 客戶端瀏覽器上的緩存(非Cookie, Cookie中的內容爲: 鍵和值均爲string類型的鍵值對)

我們可以通過在Http迴應中增加特定的頭部說明來指定瀏覽器的緩存策略; 添加頭部說明的手段既可以通過頁面指令聲明設置, 也可以通過編程方式設置.


對於圖片、Javascript腳本、CSS等資源, 可以在IIS管理器中, 右擊圖片等資源, 選擇”屬性” --> HttpHeaders後, 勾選Enable Content Expiration並設置時間即可. 一種值得推薦的手段是, 將需要緩存的資源分類, 如: image/dynamic/、image/static/, 這樣我們可以再文件夾上, 選擇屬性中的HttpHeaders進行設置. 否則, 針對每一個靜態資源設置HttpHeaders將是件非常痛苦的事情. 此外, 還可以採用一款名爲CacheRight的工具可以提供緩存資源的統一配置.


查看或設置瀏覽器緩存位置: IE --> Internet選項 --> 常規 --> 臨時Internet文件 --> 設置

Html文件的Head中的緩存設置:


<meta http-equiv="pragma" content="no-cache" />

<meta http-equiv="Cache-Control" content="no-cache" />

<meta http-equiv="expires" content="Wed, 26 Feb 1997 08:21:57 GMT" />


瀏覽器中關於Cache的3屬性:

Cache-Control:

設置相對過期時間, max-age指明以秒爲單位的緩存時間. 若對靜態資源只緩存一次, 可以設置max-age的值爲315360000000 (一萬年).

Http協議的cache-control的常見取值及其組合釋義:

no-cache: 數據內容不能被緩存, 每次請求都重新訪問服務器, 若有max-age, 則緩存期間不訪問服務器.

no-store: 不僅不能緩存, 連暫存也不可以(即: 臨時文件夾中不能暫存該資源)

private(默認): 只能在瀏覽器中緩存, 只有在第一次請求的時候才訪問服務器, 若有max-age, 則緩存期間不訪問服務器.

public: 可以被任何緩存區緩存, 如: 瀏覽器、服務器、代理服務器等

max-age: 相對過期時間, 即以秒爲單位的緩存時間.

no-cache, private: 打開新窗口時候重新訪問服務器, 若設置max-age, 則緩存期間不訪問服務器.

private, 正數的max-age: 後退時候不會訪問服務器

no-cache, 正數的max-age: 後退時會訪問服務器

點擊刷新: 無論如何都會訪問服務器.

Expires:

設置以分鐘爲單位的絕對過期時間, 優先級比Cache-Control低, 同時設置Expires和Cache-Control則後者生效.

Last-Modified:

該資源的最後修改時間, 在瀏覽器下一次請求資源時, 瀏覽器將先發送一個請求到服務器上, 並附上If-Unmodified-Since頭來說明瀏覽器所緩存資源的最後修改時間, 如果服務器發現沒有修改, 則直接返回304(Not Modified)迴應信息給瀏覽器(內容很少), 如果服務器對比時間發現修改了, 則照常返回所請求的資源.


注意:

Last-Modified屬性通常和Expires或Cache-Control屬性配合使用, 因爲即使瀏覽器設置緩存, 當用戶點擊”刷新”按鈕時, 瀏覽器會忽略緩存繼續向服務器發送請求, 這時Last-Modified將能夠很好的減小回應開銷.


ETag將返回給瀏覽器一個資源ID, 如果有了新版本則正常發送並附上新ID, 否則返回304, 但是在服務器集羣情況下, 每個服務器將返回不同的ID, 因此不建議使用ETag.


以上描述的客戶端瀏覽器緩存是指存儲位置在客戶端瀏覽器, 但是對客戶端瀏覽器緩存的實際設置工作是在服務器上的資源中完成的. 雖然剛纔我們介紹了有關於客戶端瀏覽器緩存的屬性, 但是實際上對這些屬性的設置工作都需要在服務器的資源中做設置. 我們有兩種操作手段對瀏覽器緩存進行設置, 一個是通過頁面指令聲明來設置, 另外一個是通過編程方式來設置.


瀏覽器緩存的設置手段:

第一: 通過頁面指令聲明來設置HTTP的緩存

頁面指令

<%@ OutputCache Location=”Any” Duration=”10” VaryByParam=”ProductId” VaryByHeader=”Accept-Language”%>


中的Location用來設置緩存的位置, 該屬性常見的值爲:

Any(默認): 輸出緩存可以位於任何地點, 對應於HttpCacheability.Public. 如: 客戶端瀏覽器、代理服務器或服務器本身.

Client: 只能位於發出請求的客戶端瀏覽器, 對應於HttpCacheability.Private.

Downstream: 輸出緩存可以位於除服務器本身的其他任何地方, 如: 客戶端瀏覽器、代理服務器.

Server: 輸出緩存位於Web服務器本身, 對應於HttpCacheability.Server

ServerAndClient: 輸出緩存只能位於服務器本身或客戶端瀏覽器, 對應於HttpCacheability.Private和HttpCacheability.Server

None: 禁用輸出緩存, 對應於HttpCacheability.NoCache.

VaryByParam屬性: 根據請求參數的不同而緩存不同的版本. 多個值用分號(;)分隔, *號表示爲任意參數或參數組合緩存不同版本, “none”表示只緩存一個版本.

VaryByHeader屬性: 根據請求頭來緩存不同的版本, 如同一頁面的不同語言版本.

VaryByCustom屬性: 根據自定義參數來緩存不同的版本, 如: VaryByCunstom=”browser”是系統已實現的, 根據瀏覽器名稱和版本號緩存不同的版本. 也可以, 根據自定義參數來緩存, 如: VaryByCustom=”happy”, 此時系統不知道如何解釋happy, 因此需要在Global.asax或IHttpModule實現類中重寫GetVaryByCustomString()方法, 來完成處理邏輯.

VaryByControl屬性: 根據用戶控件中的服務器控件ID來緩存不同版本.

更高級的方式, 是通過配置文件來設置HTTP的緩存.

頁面指令爲
1

<%@ OutputCache CacheProfile=”cacheconfig”%>

, 其中cacheconfig是配置文件中的緩存配置節中CacheProfile的名稱.


<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="cacheconfig" duration="10" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>


1、傳統緩存之一(404)

這個辦法是把nginx的404錯誤定向到後端,然後用proxy_store把後端返回的頁面保存。

配置:


l
ocation /fetch/ {#404定向到這裏
internal;#指明這個目錄不能在外部直接訪問到
expires 1d;#網頁的過期時間
alias /home/html/;#虛擬目錄文件系統地址要和locaion /一致,proxy_store會將文件保存到這目錄下
proxy_pass ;#後端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 ;
}
}

可以看到這個配置比404節約了不少代碼,它是用!-f來判斷請求的文件在文件系統上存不存在,不存在就proxy_pass到後端,返回同樣是用proxy_store保存。

兩種傳統緩存都有着基本一樣的優點和缺點:

缺點1:不支持帶參數的動態鏈接,比如read.php?id=1,因爲nginx只保 存文件名,所以這個鏈接只在文件系統下保存爲read.php,這樣用戶訪問read.php?id=2時會返回不正確的結果。同時不支持這種形式的首頁 和二級目錄,因爲nginx非常老實,會將這樣的請求照鏈接寫入文件系統,而這個鏈接顯然是一個目錄,所以保存失敗。這些情況都需要寫rewrite才能 正確保存。
缺點2:nginx內部沒有緩存過期和清理的任何機制,這些緩存的文件會永久性地保存在機器上,如果要緩存的東西非常多,那就會撐暴整個硬盤空間。爲此可以使用一個shell腳本定期清理,同時可以撰寫php等動態程序來做實時更新。
缺點3:只能緩存200狀態碼,因此後端返回301/302/404等狀態碼都不會緩存,假如恰好有一個訪問量很大的僞靜態鏈接被刪除,那就會不停穿透導致後端承載不小壓力。
缺點4:nginx不會自動選擇內存或硬盤作爲存儲介質,一切由配置決定,當然在當前的操作系統裏都會有操作系統級的文件緩存機制,所以存在硬盤上也不需要過分擔心大併發讀取造成的io性能問題。

nginx傳統緩存的缺點也是它和squid等緩存軟件的不同之特色,所以也可看作其優點。在生產應用中它常常用作和squid的搭檔,squid 對於帶?的鏈接往往無法阻擋,而nginx能將其訪問攔住,例如:?和在squid上會被當做兩個鏈接,所以會造成兩次穿透;而nginx只會保存一次, 無論鏈接變成還是,均不能透過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、基於memcached的緩存

nginx對memcached有所支持,但是功能並不是特別之強,性能上還是非常之優秀。


location /mem/ {
if ( $uri ~ "^/mem/([0-9A-Za-z_]*)$" )
{
set $memcached_key "$1";
memcached_pass 192.168.1.2:11211;
}
expires 70;
}


這個配置會將指明到memcached的abc這個key去取數據。

nginx目前沒有寫入memcached的任何機制,所以要往memcached裏寫入數據得用後臺的動態語言完成,可以利用404定向到後端去寫入數據。

4、基於第三方插件ncache

ncache是新浪兄弟開發的一個不錯的項目,它利用nginx和memcached實現了一部分類似squid緩存的功能,我並沒有使用這個插件的經驗,可以參考:

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是指單個文件超過2m的就不緩 存;clean_time指定一分鐘清理一次緩存。


location / {
proxy_pass ;

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;#其它的保存一分鐘
}


支持cache的0.7.44到0.7.51這幾個版本的穩定性均有問題,訪問有些鏈接會出現錯誤,所以這幾個版本最好不要在生產環境中使 用。nginx-0.7下目前所知較爲穩定的版本是0.7.39。穩定版0.6.36版也是近期更新,如果在配置裏沒有使用到0.7的一些新標籤新功能, 也可以使用0.6.36版。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章