壓縮通過減少http響應的大小來減少響應時間逸寓。如果Http請求得到更小的響應,服務器和瀏覽器之間就會有更少的包被傳送驴剔,傳輸時間就減少了碟刺。
壓縮是怎么工作的
從Http/1.1開始,瀏覽器通過在http請求頭中添加Accept-Encoding頭來支持壓縮除抛;
Accept-Encoding: gzip,deflate
如果web服務器從請求頭中發(fā)現(xiàn)Accept-Encoding頭狮杨,它可能使用Accept-Encoding指定的壓縮算法列表中的一個來壓縮響應。web服務器通過響應頭中的Content-Encoding頭來通知瀏覽器響應內(nèi)容使用了哪種壓縮算法到忽;
Content-Encoding:gzip
Gzip是目前最流行而且很有效率的壓縮方法橄教。另外一種壓縮算法是deflate,但是它稍微低效點并且不是很流行,支持deflate的瀏覽器也支持gzip喘漏,但是有些支持gzip的瀏覽器不支持deflate,所以gzip更適合作為壓縮響應的方法护蝶。
哪些需要被壓縮
很多網(wǎng)站壓縮他們的HTML文檔,但是壓縮你的scripts腳本和stylesheet樣式文件是值得的(事實上壓縮任何text類型的響應陷遮,包括XML和JSON都是是值得的)滓走,圖片和PDF文件不應該被壓縮,因為他們已經(jīng)是壓縮的了帽馋,試著壓縮他們會浪費CPU資源而且可能潛在增加文件大小搅方。
壓縮有一項成本:它會帶來額外的服務器端壓縮和客戶端解壓縮的CPU資源。為了權衡利弊绽族,你需要去考慮響應的大小姨涡,網(wǎng)絡的帶寬,以及服務器和瀏覽器之間的網(wǎng)絡距離等因素吧慢,這些信息通常是不容易獲取的涛漂。所以,一般對于超過1k或者2k的文件都是值得去壓縮的。
壓縮率
壓縮通常能減少響應70%左右的大小
代理緩存
當瀏覽器發(fā)送經(jīng)過代理的請求匈仗,情況相對會變得復雜瓢剿。假設來自不支持gzip的瀏覽器發(fā)起第一次請求到代理服務器,因為是第一次請求悠轩,所以代理服務器的緩存是空的间狂,代理把請求轉(zhuǎn)發(fā)給web服務器,web服務器作一個未壓縮的響應火架。這個未壓縮的響應被代理緩存并且發(fā)送給瀏覽器〖螅現(xiàn)在,假第二個支持gzip壓縮的請求發(fā)送到代理何鸡,代理從緩存中取出未壓縮的數(shù)據(jù)作為響應纺弊,這樣就丟失了使用gzip的能力。
更糟糕的是骡男,如果第一次請求來自支持gzip的瀏覽器而第二次請求來自一個不支持的瀏覽器淆游,這種情況下,代理緩存中有一個內(nèi)容的壓縮版本并且為不管是否支持gzip壓縮的瀏覽器都提供服務洞翩。
解決這個問題的方法是在你的web服務響應頭中添加一個Vary header字段稽犁,web服務器通知代理基于一個或多個請求頭來做不同的緩存響應。因為是否壓縮是基于Accept-Encoding頭骚亿,所有有理由在web服務器的響應的vary頭字段中包含Accept-Encoding
Vary: Accept-Encoding
這會導致代理會基于請求頭Accept-Encoding字段的每個一個值緩存不同的響應內(nèi)容版本。在我們之前的例子中熊赖,代理將緩存兩個每個響應的兩個版本:當Accept-Encoding是gzip時的壓縮內(nèi)容来屠,和Accept-Encoding完全沒有指定時的非壓縮版本。當瀏覽器發(fā)起一個帶Accept-Encoding:gzip的請求到代理震鹉,代理會取緩存中壓縮的版本并作為響應到瀏覽器俱笛,如果沒有Accept-Encoding:gzip頭,瀏覽器將受到未壓縮的版本传趾。
代理邊緣情況
雖然有90%的瀏覽器聲稱支持gzip迎膜,但是可能其中有些瀏覽器在解壓方面存在bug。一個比較安全的方法是向被證實支持壓縮的瀏覽器才提供壓縮內(nèi)容的服務浆兰,比如IE6+和Mozilla 5.0+
web服務器可以通過配置User-Agent的類型條件來對指定壓縮安全的瀏覽器提供壓縮支持磕仅,比如Apache 1.3設置如下
mod_gzip_item_include reqheader "User-Agent: MSIE [6-9]"
mod_gzip_item_include reqheader "User-Agent: Mozilla/[5-9]"
添加緩存混合這些瀏覽器的邊緣情況,最好的方法是添加User-Agent到Vary頭中
Vary: Accept-Encoding,User-Agent
這樣代理就會根據(jù)請求的Accept-Encoding和User-Agent的值來緩存不同的web服務器響應版本簸呈,便于下次請求直接作出響應榕订。但是代理基于Accept-Encoding和User-Agent請求頭的組合緩存所有請求URL的響應內(nèi)容,是不太可能的蜕便。
這個問題實質(zhì)上是平衡壓縮和緩存兩者的問題劫恒,怎么處理還是得依據(jù)網(wǎng)站的實際情況:
- 如果你的網(wǎng)站有比較少的用戶并且他們是比較小眾的(比如都使用firefox1.5),邊緣情況就可以幾乎不考慮,壓縮你的內(nèi)容并且使用Vary:Accept-Encoding两嘴,這樣就通過減少響應大小并且使用代理緩存來增強了網(wǎng)站的性能丛楚。
- 如果你更關心節(jié)省網(wǎng)絡帶寬,同樣壓縮你的內(nèi)容和使用Vary:Accept-Encoding憔辫。這樣減少了web服務器的網(wǎng)絡帶寬并且增加了被代理處理的請求數(shù)量
- 如果你有一個大的不同的用戶趣些,能夠負擔得起比較高的帶寬開銷和一個高質(zhì)量的口碑,壓縮你的內(nèi)容和使用Cache-Control:Private螺垢。這個會使代理不再緩存喧务,但是避免了邊緣情況的bug