2015-10-04 36 views
2

我使用stale-if-error提供陳舊的內容,而服務器被標記爲不健康的看着vcl_hitgracekeep對象選擇服務器。交付錯誤之後陳舊的內容「探針」之前取清漆4分unhealth

問題是:是否可以在輸入vcl子程序vcl_backend_error(新請求錯誤)後發送緩存對象。實際上,我在vcl_hit上提供緩存對象,但查看下一個圖,我沒有看到如何訪問該請求的緩存對象。

https://www.varnish-software.com/book/4.0/chapters/VCL_Basics.html

來源:https://www.varnish-software.com/book/4.0/chapters/VCL_Basics.html

+0

我不太明白你的問題。據我瞭解,在Varnish 4中,當緩存對象的生存時間到達後有新的請求到達,但在寬限時間內,Varnish將傳遞陳舊對象並向後端創建異步請求。如果這個請求失敗,陳舊對象仍然會被遞送到寬限期結束。 – Ronald

回答

2

當使用內置的VCL(見代碼波紋管):由背景/異步達到

# Built-in 'vcl_hit'. 
sub vcl_hit { 
    if (obj.ttl >= 0s) { 
     return (deliver); 
    } 

    if (obj.ttl + obj.grace > 0s) { 
     return (deliver); 
    } 

    return (fetch); 
} 
  • 如果vcl_backend_error期間由return (deliver)觸發的後端提取0你不需要擔心。這只是一個後臺線程來更新停滯的對象。停滯的內容已經交付給客戶。

  • 如果vcl_backend_error通過由return (fetch)vcl_hit期間觸發的同步後端提取而達到,則不需要擔心。錯誤將傳遞給客戶端,但你沒有選擇。停滯的對象在清漆存儲器中不可用。

但是,如果已經定製vcl_hit限制恩當後端是健康(見下文VCL例如代碼),在vcl_hit執行的return (fetch)將被作爲同步後端請求處理。客戶端將等待後端響應。如果後端請求達到vcl_backend_error並且錯誤將傳遞到客戶端。在Varnish存儲中有一個停頓的對象(在本例中停滯超過60秒),但它不會被使用。

# Customised 'vcl_hit'. 
sub vcl_hit { 
    if (obj.ttl >= 0s) { 
     return (deliver); 
    } 

    if (std.healthy(req.backend_hint)) { 
     if (obj.ttl + 60s > 0s) { 
      return (deliver); 
     } 
    } else { 
     if (obj.ttl + obj.grace > 0s) { 
      return (deliver); 
     } 
    } 

    return (fetch); 
} 

如果您希望在同步後端獲取未能提供停滯對象,在這種情況下,你需要一些額外的VCL邏輯。這個想法顯示在下面的代碼:

backend fail_be { 
    .host = "127.0.0.1"; 
    .port = "9000"; 
    .probe = { 
     .url = "/give-me-a-non-200-please"; 
     .interval = 24h; 
     .timeout = 1s; 
     .window = 1; 
     .threshold = 1; 
    } 
} 

sub vcl_recv { 
    # Force the non-healthy backend in case of restart because of a previous 
    # failed backend fetch. This will force serving stalled content using 
    # full grace during 'vcl_hit' (if possible). 
    if (req.restarts == 0) { 
     unset req.http.X-Varnish-Restarted-5xx; 
    } else { 
     if (req.http.X-Varnish-Restarted-5xx) { 
      set req.backend_hint = fail_be; 
     } 
    } 

    # ... 
} 

sub vcl_synth { 
    # 503 generated for synchronous client requests when abandoning the 
    # backend request (see 'vcl_backend_fetch') and not executing a POST. 
    if (resp.status == 503 && 
     req.method != "POST" && 
     !req.http.X-Varnish-Restarted-5xx) { 
     set req.http.X-Varnish-Restarted-5xx = "1"; 
     return (restart); 
    } 

    # ... 
} 

sub vcl_backend_fetch { 
    if (bereq.retries == 0) { 
     unset bereq.http.X-Varnish-Backend-5xx; 
    } else { 
     if (bereq.http.X-Varnish-Backend-5xx) { 
      # Jump to 'vcl_synth' with a 503 status code. 
      return (abandon); 
     } 
    } 

    # ... 
} 

sub vcl_backend_response { 
    if (beresp.status >= 500 && beresp.status < 600) { 
     set bereq.http.X-Varnish-Backend-5xx = "1"; 
     return (retry); 
    } 

    # ... 
} 

sub vcl_backend_error { 
    set bereq.http.X-Varnish-Backend-5xx = "1"; 
    return (retry); 
} 
+0

這是太多的邏輯,但你的答案是好的。謝謝。我會等待更多的答案,如果有的話更簡單,我會檢查你的答案。我正在用後端響應stale-while-revalidate填充「grace」,用stale-if-error填充「keep」,並且如果後端在同步請求中返回錯誤,我試圖使用stale-if-error,因爲緩存對象存在(因爲保留值)。 – Wiliam

+2

關於簡單性,如果您願意,可以簡化VCL邏輯:(1)總是生病的後端('fail_be')用於保持邏輯更易讀,但不是必需的(您可以將其刪除並將'req.restarts> 0 && req.http.X-Varnish-Restarted-5xx'移動到'vcl_hit'); (2)當使用Varnish Cache 4.1時(即vcl_backend _。*子例程中的邏輯)可以被高度簡化。在'vcl_backend_response'和'vcl_backend_error'中刪除'vcl_backend_fetch'並簡單地'返回(放棄)'而不是'return(retry)')。 –