varnish有個關鍵特性,爲misbehaving(行爲不端,詭異的)web服務器或者應用服務器提供保護的能力。html
當幾個客戶端請求同一個頁面的時候,varnish只發送一個請求到後端服務器,而後讓其餘幾個請求掛起並等待返回結果;得到結果後,其它請求再複製後端的結果發送給客戶端。有些產品中須要調用其餘來將請求合併,而varnish自動作這些。web
但若是同時有數以千計的請求,那麼這個等待隊列將變得龐大,這將致使2類潛在問題:後端
驚羣問題(thundering herd problem),即忽然釋放大量的線程去複製後端返回的結果,將致使負載急速上升;緩存
沒有用戶喜歡等待;服務器
爲了解決這類問題,能夠配置varnish在緩存對象因超時失效後再保留一段時間,以給那些等待的請求返回過時的內容(stale content)。app
爲了提供給用戶過時的內容,咱們必須先有這些內容。所以咱們在VCL中配置以下,使得varnish能在內容過時事後依然保持2分鐘:異步
sub vcl_backend_response { set beresp.grace = 2m; }
如今Varnish容許在對象過時後2分鐘內提供給客戶端。同時varnish也將刷新這個對象。刷新動做是異步發生的,發生在新的對象將替換老對象的同時。ide
咱們能夠在vcl_hit中增長代碼來影響這個邏輯的工做。默認VCL是這樣:fetch
sub vcl_hit { if (obj.ttl >= 0s) { // A pure unadultered hit, deliver it return (deliver); } if (obj.ttl + obj.grace > 0s) { // Object is in grace, deliver it // Automatically triggers a background fetch return (deliver); } // fetch & deliver once we get the result return (fetch); }
若是你開啓了健康檢測,要是後端有問題只能提供給客戶端過時的對象時,你就能檢測到。用以下的if語句替換掉上面的第二個if語句塊:spa
if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) { return (deliver); } else { return (fetch); }
總之,優雅模式解決下面2個問題:
提供過時內容給客戶端以免請求堆積。
若是你容許varnish能夠提供過時的內容。
你可使用inline C來擴展Varnish。注意,這種方式您可能嚴重損毀varnish。C代碼運行在Varnish緩存進程中,若是你的C代碼有錯誤,緩存進程將crash。
一個使用inline C的功能是記錄日誌到syslog:
# The include statements must be outside the subroutines. C{ #include <syslog.h> }C sub vcl_something { C{ syslog(LOG_INFO, "Something happened at VCL line XX."); }C }
要使用inline C你須要經過vcc_allow_inline_c參數開啓此功能。