後端機器返回錯誤的gzip數據致使varnish出現503錯誤

近期,筆者維護的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/文件路徑

此次服務器返回了沒有壓縮過的內容,明顯是正確的了。

分析結果:

  1. 默認狀況下,不管客戶端是否支持gzip, varnish在請求源服務器時,會自動增長Accept-Encoding:gzip指令,期待獲取壓縮內容

  2. varnish取到結果後,會根據vcl_backend_response事件中的beresp.do_gzip = true/false指令,決定是否把內容gzip壓縮後緩存起來(顯然壓縮後緩存,會節省大量內存或磁盤資源),若是這個指令沒有設置,則使用緣由內容緩存,不做壓縮任何壓縮處理。

  3. 不管源服務器是否支持gzip壓縮,不管緩存內容是否已經gzip壓縮,只要客戶端支持gzip壓縮,varnish會返回gzip的內容。另外一面,若是客戶端不支持gzip壓縮,varnish會將緩存的gzip壓縮過的內容進行解壓,再發送給客戶端。

  4. varnish是設計就是以最佳性能爲考慮的,因此默認是啓用gzip壓縮的。

知道這幾個原理後,若是源機器返回了非法的gzip內容,咱們能夠用如下任何一個方法處理:

  1.  讓源機器返回正確的gzip內容,或禁止源機器gzip壓縮。

  2. 讓varnish在請求源機器時,指望獲取不壓縮內容

  3. 完全禁止掉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錯誤的問題獲得瞭解決。

相關文章
相關標籤/搜索