varnish 4 - 放弃,vcl_synth,并用新的 headers 重新启动请求

varnish 4 - abandon, vcl_synth, and restarting requests with new headers

我已经询问并收到了一个很棒的答案,关于如何从后端获取错误以强制从此处找到的陈旧缓存(宽限期)提供服务:

但现在逻辑需要一个额外的步骤:我目前包括以下代码

sub vcl_backend_fetch {
  if (bereq.retries == 0) {
    unset bereq.http.X-Varnish-Backend-5xx;
    unset bereq.http.X-Varnish-Backend-206;
  } else {
    if (bereq.http.X-Varnish-Backend-5xx) {
      return (abandon);
    }
    if (bereq.http.X-Varnish-Backend-206) {
      return (abandon);
    }
  }
}

sub vcl_synth {
  if (resp.status == 503 &&
    req.method != "POST" &&
    !req.http.X-Varnish-Restarted-5xx) {
    set req.http.X-Varnish-Restarted-5xx = "1";
    return (restart);
  }

  if (resp.status == 503 &&
    req.method != "POST" &&
    !req.http.X-Varnish-Restarted-206) {
    set req.http.X-Varnish-Restarted-206 = "1";
    return (restart);
  }

}

显然 vcl_synth 中的第二个 if 语句实际上与第一个相同,除了它正在寻找的 header。我需要区分 206 以使用不同的请求 header 重新启动,但我不确定如何。问题是,如果后端 return 是 206,则其余逻辑将放弃后端提取(使用 503 交给 vcl_synth),然后 vcl_synth 重新启动请求强制服务优雅缓存 objects。但是,如果用户没有 object 到 return 的宽限缓存,则用户看到的是 503 而不是 206。

在意识到这种思路是不可能的之前,我尝试让 vcl_backend_fetch return 合成器 (206),以便 vcl_synth 可以使用 resp.status区分,并在重新启动请求之前添加不同的请求header。然后我就可以在 vcl_miss 中寻找那个 header,如果它在那里,我可以第二次重新启动整个请求,并强制它从通常的后端为 206 提供服务。

TL;DR:我如何在 vcl_backend_fetch 放弃中区分两种不同的情况,让 vcl_synth 以两个不同的 header 重新启动请求?

我很确定在 vcl_backend_fetch 中无法执行任何操作以放弃请求并将某种标志传输到 vcl_synth

我不确定我是否完全理解您的用例,但似乎需要这样的东西:

sub vcl_synth {
    if (resp.status == 503 &&
        req.method != "POST" &&
        !req.http.X-Varnish-Restarted-5xx) {
        # Let's restart the request for the first time and try to 
        # serve grace content. This could select an always-sick
        # backend during vcl_recv.
        set req.http.X-Varnish-Restarted-5xx = "1";
        return (restart);
    }

    if (resp.status == 503 &&
        req.method != "POST" &&
        req.http.X-Varnish-Restarted-5xx &&
        !req.http.X-Varnish-Restarted-206) {
        # Grace content was not available after the first restart. Let's 
        # restart again the request and try to serve content using some
        # other backend.
        set req.http.X-Varnish-Restarted-206 = "1";
        return (restart);
    }
}