天天看點

轉:Squid緩存命中率調整

公司的網站使用Squid

2.6STABLE2作緩存加速伺服器,緩存的命中率一直不好,最好也隻能達到90%,折騰了許久,終于發現影響最大的原來隻是一個小參數,不過期間也學

到了不少東西~

起初,考慮緩存命中率不高,考慮是不是給Squid的記憶體不夠,是以就加大了記憶體配置,2G記憶體的機器給Squid

1G用,測試了兩天,結果基本沒有什麼大的改變;于是調整refresh_pattern的參數,增大内容緩存時間,測試了兩天,效果也不理想。

從kxn的文章中知道可以使用Expires子產品讓Apache給檔案指定緩存時間,期望可以提高緩存性能,于是在伺服器上:

ExpiresActive On

ExpiresDefault A2592000

結果第二天一早發現緩存命中率竟然比前一天還下降了2個百本點,有點暈了~

于是将cachemgr配置起來,詳細地檢查squid的運作狀況,發現1G的記憶體緩存實際隻用了不到300M,是以顯然不是記憶體不夠的問題。

為了充分利用記憶體,将maximum_object_size_in_memory調大到128KB,讓其可以緩存更大的檔案,而不是預設的

8KB。順手将ufs換成aufs,啟用異步IO。

之後情況稍有改善,1個小時之後,記憶體的占用達到了1G,但命中率并沒有明顯上升。

于是又調整了記憶體的覆寫政策(memory_replacement_policy),聽從kxn的教誨,使用lru,發現變化不大,也許是我們的

通路量還不大的原因吧。

這時候緩存命中率仍然在90%以下徘徊。是不是我們的網站結構影響隻能達到這麼高呢?但是網站結構我沒有辦法改變,是以還是要從其他方面入手來解決

問題。

于是使用Cache Manager 仔細的檢視各個統計資料,當看到In-Memory and In-Transit

Objects項目時,發現一個問題,那就是所有的網頁檔案都顯示NOT_IN_MEMORY,這就比較奇怪了,問什麼通路量最大的網頁檔案竟然沒有被緩

存到記憶體呢?是因為檔案太大還是因為檔案請求的數量太少,是以才沒有被緩存呢?于是找了一個頁面作測試,使用工具檢視了傳回的大小,隻有40K多一些,與

我的maximum_object_size_in_memory最大值128KB還有相當大的差距,是以不可能是這個原因。于是有使用ab程式對這個頁

面做了1000次請求,心想這下總會緩存了吧。可是檢視緩存内容,依然沒有,而且不但記憶體中沒有,就連硬碟上也沒有!

至此得出結論,一定是什麼原因阻止了Squid對這些網頁進行緩存。仔細的檢查In-Memory and In-Transit

Objects中的内容,發現IN_MEMORY 狀态的對象基本都是jpg和gif圖像檔案,html,css等文本檔案内容則都沒有緩存。

這兩種檔案有什麼不同嗎?記憶中Squid也沒有對這些檔案類型的設定呀,refresh_pattern對所有的靜态檔案的設定也都是一緻的,所

以差異不應該來源于squid本身——也就是因為這種記憶使得我後來多費了許多的功夫~

在Apache上找到了文本檔案與圖像檔案之間設定的差異——deflate壓縮。是不是所有使用deflate壓縮的内容都不會緩存呢?使用同樣

的squid軟體版本及配置檔案,相同的Apache軟體版本和配置,快速的搭建了一套測試環境。squid隻有1台,重建其磁盤緩沖區,重新啟動

squid,觀察記憶體中對象的變化。果然,對于deflate壓縮的内容,squid記憶體中沒有緩存,磁盤也找不到。停止apache的deflate功

能,重新請求頁面,立即在squid的記憶體中查到了内容的緩存,這麼看來是squid和deflate不太相容了?

好吧,先将産品環境Apache的deflate停掉,過了一段時間,有兩台squid的緩存命中了提高到了94%,雖然隻提升了4個百分點,但是

這充分驗證了squid和deflate不相容的觀點。

然而,事情到此才剛剛開始!

難道Squid真的無法緩存deflate壓縮的頁面嗎?好吧google一下,squid+deflate,在squid的郵件清單中找到了一些

讨論deflate的東西,屬于比較古老的吧,說因為deflate壓縮之後,會産生Content-Encoding:

gzip這樣的HTTP頭部,屬于HTTP/1.1的内容,而Squid并不完全相容HTTP/1.1之類的,需要用Transfer-Encoding

之類的代替,可是mod_deflate和mod_gzip産生的頭部就是Content-Encoding,怎麼辦?

為了解決這個問題,引入了另一個Apache的子產品,mod_headers,用它來改寫HTTP應答的頭部,将Content-Encoding

更改給Transfer-Encoding,可是,很自然的,頁面一片亂碼!說明此路不通啊!

又以Content-Encoding為關鍵字,快速的搜尋了一下squid

2.6STABLE2的源代碼,也沒有發現幾個地方用到這個東西,無果。

繼續Google之,squid+can’t cache+Content-Encoding找到一篇文章,其中說’SQUID would

never bother to cache ANYTHING that had

a “Vary:” header on it.’ 看來Squid緩存内容與Vary:

頭部有關系。再次檢查一下HTTP請求傳回的頭部内容,發現對于deflate壓縮的内容,擁有”Vary:

Accept-Encoding”這樣一個頭部,而沒有經過deflate壓縮的内容則沒有這個頭部,這次看來問題比較清楚了,因為deflate壓縮添

加了Vary: Accept-Encoding這個頭部,導緻了内容無法被squid緩存。

那麼難道真的沒有辦法讓squid緩存deflate壓縮之後的内容嗎?

基于上面的經驗,很自然的想到使用mod_headers子產品的功能将Vary頭抹掉Squid不就可以緩存了嗎?後來一想,這樣會有其它問題:

1)如果使用者浏覽器不支援gzip壓縮功能,那麼将無法正常的浏覽網頁;2)其它可能很重要的Vary内容也沒有了,可能會導緻更大的隐患。那麼這種辦法

不行。

還有其它的辦法嗎?再次的快速搜尋了Squid的源檔案中關于Vary的内容,在Changelog中找到了這麼一條:

- Full ETag/Vary support, caching responses which varies with request

details (browser, language etc).

也就是說已經完全支援帶ETag/Vary頭部的内容緩存了。這一條出現在Changes to

squid-2.6.STABLE1,也就是說在Squid2.6STABLE1就已經完全實作了這個功能,那麼2.6STABLE2應該沒有問題,會不

會是2.6STABLE2的BUG呢,查詢了一下2.6系列的所有Changelog,沒有提到此故障的資訊。推斷我們的故障要麼由一個未知BUG導緻,

要麼是自己配置不當。BUG的問題我無法确認,隻能先從配置入手。

找來一份2.6STABLE2帶的預設配置檔案,搜尋Vary,第一條:

# TAG: cache_vary

# Set to off to disable caching of Vary:in objects.

#

#Default:

# cache_vary on

難道我的配置檔案是off不成?趕緊檢查,發現還真是off,sign,原來就是這個問題折磨我,改成on,将Apache的Deflate配置啟用,再

觀察記憶體對象,發現靜态網頁真的被緩存了!

郁悶了許久,終于可以松口氣了。

過了一會兒,再檢視Squid的狀态,發現緩存命中率沒有下降,穩定在94%左右。

也許Squid還有什麼可挖掘的空間吧,改天接着折騰!

後記:Squid對Vary和Etag的支援屬于2.6的一項主要改進,這一特性改進Squid對HTTP/1.1标準的支援。在将Squid更新

至2.6之前,也看過他的Changelog,但當時并不明白Vary到底有什麼用途,這麼一折騰,明白了不少。看來應該把HTTP/1.1的标準再好好

研讀一下。

繼續閱讀