如何解决 Varnish purger 在 1000 毫秒后超时,0 个字节中有 0 个字节收到 cURL 错误 28

How to solve Varnish purger that times out after 1000 milliseconds with 0 out of 0 bytes received with cURL error 28

使用 Varnish (5.2) 进行缓存工作正常,但是当更改站点上的某些内容时,缓存不会刷新并且陈旧的内容不断显示。我可以看到有一个清除队列,但没有 BAN 正在处理。 Drupal (8) 与 Varnish Purge 模块形成一个队列来获取 Varnish 中的缓存标签失效并 drush 处理它:

drush p:queue-work
 ------------------------ -----
  Succeeded                0
  Failed                   100
  Currently invalidating   0
  Not supported            0
 ------------------------ -----
In QueueCommands.php line 529:  Over 40% failed, please check the logs!

然后日志中出现这条消息:

purger_varnish_84f7afee13: item failed due GuzzleHttp\Exception\ConnectException, details (JSON): {"msg":"cURL error 28: Operation timed out after 1000 milliseconds with 0 out of 0 bytes received (see https:\/\/curl.haxx.se\/libcurl\/c\/libcurl-errors.html)","uri":"https:\/\/127.0.0.1:6081\/","method":"BAN","guzzle_opt":{"http_errors":true,"connect_timeout":1,"timeout":1,"verify":false},"headers":{"user-agent":"varnish_purger module for Drupal 8.","cache-tags":"config:contact.form.personal"}}

使用 cURL 手动清除 有效:

curl -X BAN http://127.0.0.1:6081/ -H "Cache-Tags: node:1042"

可能是什么问题,Varnish 似乎不接受连接或类似的东西?

/etc/varnish/usr.vcl 的内容:

vcl 4.0;

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

acl purge {
"127.0.0.1";
}

# Respond to incoming requests.
sub vcl_recv {
# Add an X-Forwarded-For header with the client IP address.
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
}
else {
set req.http.X-Forwarded-For = client.ip;
}
}
# Only allow PURGE requests from IP addresses in the 'purge' ACL.
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed."));
}
return (hash);
}
# Only allow BAN requests from IP addresses in the 'purge' ACL.
if (req.method == "BAN") {
# Same ACL check as above:
if (!client.ip ~ purge) {
return (synth(403, "Not allowed."));
}
# Logic for the ban, using the Cache-Tags header. For more info
# see https://github.com/geerlingguy/drupal-vm/issues/397.
if (req.http.Cache-Tags) {
ban("obj.http.Cache-Tags ~ " + req.http.Cache-Tags);
}
else {
return (synth(403, "Cache-Tags header missing."));
}
# Throw a synthetic page so the request won't go to the backend.
return (synth(200, "Ban added."));
}
if (req.method == "URIBAN") {
    ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
    # Throw a synthetic page so the request won't go to the backend.
    return (synth(200, "Ban added."));
  }
# Only cache GET and HEAD requests (pass through POST requests).
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Pass through any administrative or AJAX-related paths.
if (req.url ~ "^/status.php$" ||
req.url ~ "^/update.php$" ||
req.url ~ "^/admin$" ||
req.url ~ "^/admin/.*$" ||
req.url ~ "^/flag/.*$" ||
req.url ~ "^.*/ajax/.*$" ||
req.url ~ "^.*/ahah/.*$") {
return (pass);
}

# Removing cookies for static content so Varnish caches these files.
if (req.url ~ "(?i).(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)\?$") {
unset req.http.Cookie;
}


if (req.http.Cookie) {

    set req.http.Cookie = ";" + req.http.Cookie;
    set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
    set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; =");
    set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
    set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

    if (req.http.Cookie == "") {
      unset req.http.Cookie;
}
    else {
      return (pass);
    }
}


}
# Set a header to track a cache HITs and MISSes.
sub vcl_deliver {
# Remove ban-lurker friendly custom headers when delivering to client.
unset resp.http.X-Url;
unset resp.http.X-Host;
# Comment these for easier Drupal cache tag debugging in development.
#unset resp.http.Cache-Tags;
#unset resp.http.X-Drupal-Cache-Contexts;
if (obj.hits > 0) {
set resp.http.Cache-Tags = "HIT";
}
else {
set resp.http.Cache-Tags = "MISS";
}
}
# Instruct Varnish what to do in the case of certain backend responses (beresp).
sub vcl_backend_response {
# Set ban-lurker friendly custom headers.
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
# Cache 404s, 301s, at 500s with a short lifetime to protect the backend.
if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
set beresp.ttl = 10m;
}
# Don't allow static files to set cookies.
# (?i) denotes case insensitive in PCRE (perl compatible regular expressions).
# This list of extensions appears twice, once here and again in vcl_recv so
# make sure you edit both and keep them equal.

if (bereq.url ~ "(?i).(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset beresp.http.set-cookie;
}
# Allow items to remain in cache up to 6 hours past their cache expiration.
set beresp.grace = 6h;
}

我使用 NGINX 代理通过 Varnish 启用 SSL,nginx 服务器配置的内容:

server {
    listen 443 ssl http2;
    server_name test.example.com;
    port_in_redirect off;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
      proxy_pass http://127.0.0.1:6081;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto https;
      proxy_set_header HTTPS "on";
      proxy_set_header If-Modified-Since $http_if_modified_since;
      proxy_buffering on;
      proxy_buffer_size   128k;
      proxy_buffers   4 256k;
      proxy_busy_buffers_size   256k;
    }
}

server {
   listen 8080;
   server_name test.example.com;
   root /home/example/domains/test/public_html/web;
   index index.php index.html index.htm index.nginx-debian.html;
   port_in_redirect off;

   location / {
      try_files $uri $uri/ /index.php?$query_string;
   }

   location ~ \.php$ {
      include snippets/fastcgi-php.conf;
      fastcgi_pass 127.0.0.1:9000;
   }
}

server {
    listen 80;
    if ($host = test.example.com) {
        return 301 https://$host$request_uri;
    }
    server_name test.example.com;
    return 404;
}

Drush 无法通过 TLS.

连接到端口 6081 上的 varnish

您的日志行表明您正在使用以下 URL 连接到 Varnish:https://127.0.0.1:6081/.

Varnish 的开源版本不支持原生 TLS,这就是您在 Nginx 中终止它的原因。

2 种可能的解决方案:

  • 要么将 url 更改为 http://127.0.0.1:6081 以使用纯 HTTP
  • 要么将 url 更改为 https://127.0.0.1 以通过 Nginx 使用 HTTPS

如果我是你,我会选择前者,并且只使用纯 HTTP 进行失效。它发生在内部,不会暴露在互联网上,因此使用常规 HTTP 非常安全。