如何解决Varnish清除程序,该清除程序在1000毫秒后超时,收到0个字节中的0个字节,出现cURL错误28

问题描述

使用Varnish(5.2)进行缓存可以正常工作,但是在站点上进行某些更改时,不会刷新缓存,并且会一直显示陈旧的内容。我可以看到有一个清除队列,但是没有BAN被处理。具有Varnish Purge模块的Drupal(8)形成队列,以获取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)=","; \1=");
    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上的清漆。

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

Varnish的开源版本不支持本地TLS ,这就是为什么要在Nginx中终止它。

2种可能的解决方案:

  • 您可以将网址更改为http://127.0.0.1:6081以使用纯HTTP
  • 您可以将网址更改为https://127.0.0.1以便通过Nginx使用HTTPS

如果我是我,我会选择前者,只是使用纯HTTP进行无效。它在内部发生,它没有暴露于互联网,因此使用常规HTTP是非常安全的。