公司的網站使用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的標準再好好 研讀一下。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/chinalinuxzend/archive/2007/09/12/1781563.aspx