近期,筆者維護的varnish服務器,不按期出現503錯誤,按照以往經驗,調整超時時間、請求和響應header 正文緩衝區大小,均無解。緩存
而後,只有從varnish自己的行爲入手,在varnish機器上啓動varnishlog 觀察日誌,發現有一處異常服務器
ObjHeader Content-Length: 164curl
Fetch_Body 3 length stream性能
Gzip Gunzip error: -3 (incorrect header check)fetch
FetchError Invalid Gzip data: incorrect header checkurl
Gzip u F - 2 0 0 0 0spa
從字面上看,是gzip數據格式致使的,而後就反覆猜測,有多是源服務器返回了錯誤的gzip數據,使用curl訪問源服務器:命令行
curl -i -H "Accept-Encoding:gzip" -H "Host:域名" http://源服務器ip/文件路徑 設計
輸出結果:日誌
根據源服務器的響應header Content-Encoding:gzip 明確告訴咱們,正文部分已經使用gzip壓縮,可是觀察輸出,卻很詭異,輸出的倒是明文的未壓縮過的內容,但最後一行,全是空字符,最後一個字符,卻是很像是gzip壓縮過的內容,說明服務器欺騙了咱們,雖然告訴咱們內容是gzip壓縮過的,但實際上倒是不正確的gzip結果。
而後,咱們再嘗試獲取不壓縮的內容:
curl -i -H "Host:域名" http://源服務器ip/文件路徑
此次服務器返回了沒有壓縮過的內容,明顯是正確的了。
分析結果:
默認狀況下,不管客戶端是否支持gzip, varnish在請求源服務器時,會自動增長Accept-Encoding:gzip指令,期待獲取壓縮內容
varnish取到結果後,會根據vcl_backend_response事件中的beresp.do_gzip = true/false指令,決定是否把內容gzip壓縮後緩存起來(顯然壓縮後緩存,會節省大量內存或磁盤資源),若是這個指令沒有設置,則使用緣由內容緩存,不做壓縮任何壓縮處理。
不管源服務器是否支持gzip壓縮,不管緩存內容是否已經gzip壓縮,只要客戶端支持gzip壓縮,varnish會返回gzip的內容。另外一面,若是客戶端不支持gzip壓縮,varnish會將緩存的gzip壓縮過的內容進行解壓,再發送給客戶端。
varnish是設計就是以最佳性能爲考慮的,因此默認是啓用gzip壓縮的。
知道這幾個原理後,若是源機器返回了非法的gzip內容,咱們能夠用如下任何一個方法處理:
讓源機器返回正確的gzip內容,或禁止源機器gzip壓縮。
讓varnish在請求源機器時,指望獲取不壓縮內容
完全禁止掉varnish的全部gzip壓縮功能(向客戶端發送不壓縮的內容——不管客戶端是否支持gzip; 請求源服務器時,指望獲取不壓縮內容)
以上三個方法,任選 一個,便可解決這個問題:
第2條的配置文件方法(在vcl文件中設置):
sub vcl_backend_fetch {
unset bereq.http.Accept-Encoding;
return (fetch);
}
第3條解決方法:
varnishd啓動時,使用-p http_gzip_support=off 徹底關閉掉gzip支持,若是是使用yum安裝,可在/et/sysconfig/varnish文件中指定
若是varnish已經啓動,不容許重啓,則可在運行時修改它, 使用 varnishadm 命令,進入命令行界面,查看參數:
param.show
可直接輸入help, 查看擴展的指令, 使用如下命令全局關閉gzip支持:
param.set http_gzip_support off
通過這樣處理後,偶爾返回503錯誤的問題獲得瞭解決。