【问题标题】:503 Backend fetch failed and "VSM: Could not get hold of varnishd, is it running?" but it is active503 后端获取失败和“VSM:无法获取 varnishd,它正在运行吗?”但它是活跃的
【发布时间】:2021-12-17 09:14:14
【问题描述】:

我在 Nginx 上使用 Drupal 安装 Varnish 时遇到问题

nginx.conf:

user               daemon daemon;

worker_processes  auto;
error_log         "/opt/bitnami/nginx/logs/error.log";
pid               "/opt/bitnami/nginx/tmp/nginx.pid";

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format    main '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status  $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';
    access_log    "/opt/bitnami/nginx/logs/access.log";

    client_body_temp_path  "/opt/bitnami/nginx/tmp/client_body" 1 2;
    proxy_temp_path        "/opt/bitnami/nginx/tmp/proxy" 1 2;
    fastcgi_temp_path      "/opt/bitnami/nginx/tmp/fastcgi" 1 2;
    scgi_temp_path         "/opt/bitnami/nginx/tmp/scgi" 1 2;
    uwsgi_temp_path        "/opt/bitnami/nginx/tmp/uwsgi" 1 2;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         off;
    #gzip               off;
    #gzip_http_version  1.0;
    #gzip_comp_level    2;
    #gzip_proxied       any;
    #gzip_types         text/plain text/css text/js text/xml text/javascript application/javascript application/json application/xml application/xml+rss image/svg+xml;
    keepalive_timeout   65;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

    client_max_body_size 80M;
    server_tokens off;

    include  "/opt/bitnami/nginx/conf/server_blocks/*.conf";

    # HTTP Server
    server {
        # Port to listen on, can also be set in IP:PORT format
        listen  8080;

        include  "/opt/bitnami/nginx/conf/bitnami/*.conf";

    set_real_ip_from 127.0.0.1;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    location / {
    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_pass http://127.0.0.1:8080;   
    }

    location /status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    }

    location ~* .(jpg|jpeg|png|gif|ico|css|js|pdf)$ { 
    expires 7d;
    }

  }
}

drupal-https-server-block:

server {
  # Port to listen on, can also be set in IP:PORT format
  listen 443 ssl http2 default_server;
  root /opt/bitnami/drupal;
  # Catch-all server block See: 
  # https://nginx.org/en/docs/http/server_names.html#miscellaneous_names
  server_name _; 
  ssl_certificate bitnami/certs/server.crt; 
  ssl_certificate_key bitnami/certs/server.key; 
  location / {  
        # Set recommended by Nginx version
        proxy_http_version 1.1; 
    proxy_pass http://127.0.0.1:8080;
        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 X-Forwarded-Port 443;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Server $host;
        try_files $uri /index.php?$query_string;
      }

  location = /favicon.ico { log_not_found off; access_log off;
  }
  location = /robots.txt { allow all; log_not_found off; access_log off;
  }
  location ~ ^/sites/.*/private/ { return 403;
  }
  # Block access to scripts in site files directory
  location ~ ^/sites/[^/]+/files/.*\.php$ { deny all;
  }
  # Allow "Well-Known URIs" as per RFC 5785
  location ~* ^/.well-known/ { allow all;
  }
  location @rewrite { rewrite ^/(.*)$ /index.php?q=$1;
  }
  # Don't allow direct access to PHP files in the vendor directory.
  location ~ /vendor/.*\.php$ { deny all; return 404;
  }
  # Fighting with Styles? This little gem is amazing.
  location ~ ^/sites/.*/files/styles/ { try_files $uri @rewrite;
  }
  # Handle private files through Drupal. Private file's path can come with a 
  # language prefix.
  location ~ ^(/[a-z\-]+)?/system/files/ { try_files $uri /index.php?$query_string;
  }
  location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { 
  try_files $uri @rewrite; 
  expires max; 
  log_not_found off;
  }
  location ~ \.php$|^/update.php { 
  fastcgi_read_timeout 300; 
  fastcgi_pass unix:/opt/bitnami/php/var/run/www.sock; 
  fastcgi_index index.php; 
  fastcgi_param SCRIPT_FILENAME $request_filename; 
  fastcgi_split_path_info ^(.+?.php)(|/.*)$; 
  include fastcgi_params;
  }
  include "/opt/bitnami/nginx/conf/bitnami/*.conf";
}

drupal-服务器块:

 server {
    # Port to listen on, can also be set in IP:PORT format
    listen 8080 http2 default_server; 
    root /opt/bitnami/drupal;
    # Catch-all server block See: 
    # https://nginx.org/en/docs/http/server_names.html#miscellaneous_names
    server_name _; 
    location = /favicon.ico { log_not_found off; access_log off;
    }
    location = /robots.txt { allow all; log_not_found off; access_log off;
    }
    location /static/fonts  { add_header "Access-Control-Allow-Origin" *;  alias /opt/bitnami/drupal/libraries/bootstrap/fonts/;
    }
    location ~ ^/sites/.*/private/ { return 403;
    }
    # Block access to scripts in site files directory
    location ~ ^/sites/[^/]+/files/.*\.php$ { deny all;
    }
    # Allow "Well-Known URIs" as per RFC 5785
    location ~* ^/.well-known/ { allow all;
    }
    location / { 

    if ($request_filename ~* ^.?/([^/]?)$) { 
    set $filename $1;
    }

    if ($filename ~* ^.*?\.(eot)|(ttf)|(woff)$){
           add_header Access-Control-Allow-Origin *;
    }

    try_files $uri /index.php?$query_string;
    }
    location @rewrite { rewrite ^/(.*)$ /index.php?q=$1;
    }
    # Don't allow direct access to PHP files in the vendor directory.
    location ~ /vendor/.*\.php$ { deny all; return 404;
    }
    # Fighting with Styles? This little gem is amazing.
    location ~ ^/sites/.*/files/styles/ { try_files $uri @rewrite;
    }
    # Handle private files through Drupal. Private file's path can come with a 
    # language prefix.
    location ~ ^(/[a-z\-]+)?/system/files/ { try_files $uri 
      /index.php?$query_string;
    }
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { try_files $uri @rewrite; 
      expires max; log_not_found off;
    }
    location ~ \.php$|^/update.php { 
    fastcgi_read_timeout 300; 
    fastcgi_pass unix:/opt/bitnami/php/var/run/www.sock; 
    fastcgi_index index.php; 
        fastcgi_param SCRIPT_FILENAME $request_filename; 
    fastcgi_split_path_info ^(.+?.php)(|/.*)$; 
    include fastcgi_params;
    }        
    include "/opt/bitnami/nginx/conf/bitnami/*.conf";
  }

/etc/systemd/system/varnish.service:

[Unit]
Description=Varnish HTTP accelerator
Documentation=https://www.varnish-cache.org/docs/6.1/ man:varnishd

[Service]
Type=simple
LimitNOFILE=131072
LimitMEMLOCK=82000
ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -f /etc/varnish/default.vcl -S /etc/varnish/secret$
ExecReload=/usr/share/varnish/varnishreload
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
PrivateDevices=true

[Install]
WantedBy=multi-user.target

/etc/default/varnish:

DAEMON_OPTS="-a :80 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m"

default.vcl:

# This is the VCL configuration Varnish will automatically append to your VCL
# file during compilation/loading. See the vcl(7) man page for details on syntax
# and semantics.
# New users is recommended to use the example.vcl file as a starting point.
# 

vcl 4.1;

 sub vcl_recv {
   #if (req.http.host) {
    #set req.http.host = req.http.host.lower();
     #}
     if (req.method == "PRI") {
         /* This will never happen in properly formed traffic (see: RFC7540) */
         return (synth(405));
     }
     if (!req.http.host &&
       req.esi_level == 0 &&
       req.proto ~ "^(?i)HTTP/2") {
         /* In HTTP/1.1, Host is required. */
         return (synth(400));
     }
     if (req.method != "GET" &&
       req.method != "HEAD" &&
       req.method != "PUT" &&
       req.method != "POST" &&
       req.method != "TRACE" &&
       req.method != "OPTIONS" &&
       req.method != "DELETE" &&
       req.method != "PATCH") {
         /* Non-RFC2616 or CONNECT which is weird. */
         return (pipe);
     }
 
     if (req.method != "GET" && req.method != "HEAD") {
         /* We only deal with GET and HEAD by default */
         return (pass);
     }
     if (req.http.Authorization || req.http.Cookie) {
         /* Not cacheable by default */
         return (pass);
     }
     return (hash);
 }

 sub vcl_pipe {
    # By default Connection: close is set on all piped requests, to stop
     # connection reuse from sending future requests directly to the
     # (potentially) wrong backend. If you do want this to happen, you can undo
     # it here.
     # unset bereq.http.connection;
     return (pipe);
 }
 
 sub vcl_pass {
     return (fetch);
 }
 
  sub vcl_hash {
      hash_data(req.url);
      if (req.http.host) {
          hash_data(req.http.host);
      } else {
          hash_data(server.ip);
      }
      return (lookup);
  }
# 
  sub vcl_purge {
      return (synth(200, "Purged"));
  }
# 
  sub vcl_hit {
      return (deliver);
  }
# 
  sub vcl_miss {
      return (fetch);
  }
# 
  sub vcl_deliver {
      return (deliver);
  if (obj.hits > 0) { set resp.http.Cache-Tags = "HIT";
  }
  else { set resp.http.Cache-Tags = "MISS";
  }
  }
# 
# /* * We can come here "invisibly" with the following errors: 500 & 503 */
  sub vcl_synth {
      set resp.http.Content-Type = "text/html; charset=utf-8";
      set resp.http.Retry-After = "5";
      set resp.body = {"<!DOCTYPE html>
  <html>
    <head>
      <title>"} + resp.status + " " + resp.reason + {"</title>
    </head>
    <body>
      <h1>Error "} + resp.status + " " + resp.reason + {"</h1>
      <p>"} + resp.reason + {"</p>
      <h3>Guru Meditation:</h3>
      <p>XID: "} + req.xid + {"</p>
      <hr>
      <p>Varnish cache server</p>
    </body>
  </html>
  "};
      return (deliver);
  }
# 
# #######################################################################
# # Backend Fetch
# 
  sub vcl_backend_fetch {
      if (bereq.method == "GET") {
          unset bereq.body;
      }
      return (fetch);
  }
# 
  sub vcl_backend_response {
      if (bereq.uncacheable) {
          return (deliver);
      } else if (beresp.ttl <= 0s ||
        beresp.http.Set-Cookie ||
        beresp.http.Surrogate-control ~ "(?i)no-store" ||
        (!beresp.http.Surrogate-Control &&
          beresp.http.Cache-Control ~ "(?i:no-cache|no-store|private)") ||
        beresp.http.Vary == "*") {
          #Mark as "Hit-For-Miss" for the next 2 minutes
          set beresp.ttl = 120s;
          set beresp.uncacheable = true;
      }
      return (deliver);
  }
# 
  sub vcl_backend_error {
      set beresp.http.Content-Type = "text/html; charset=utf-8";
      set beresp.http.Retry-After = "5";
      set beresp.body = {"<!DOCTYPE html>
  <html>
    <head>
      <title>"} + beresp.status + " " + beresp.reason + {"</title>
    </head>
    <body>
      <h1>Error "} + beresp.status + " " + beresp.reason + {"</h1>
      <p>"} + beresp.reason + {"</p>
      <h3>Guru Meditation:</h3>
      <p>XID: "} + bereq.xid + {"</p>
      <hr>
      <p>Varnish cache server</p>
    </body>
  </html>
  "};
      return (deliver);
  }
# 
# #######################################################################
# # Housekeeping
  
  sub vcl_init {
      return (ok);
  }

  sub vcl_fini {
      return (ok);
  }

backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 600s;
.first_byte_timeout = 600s;

.probe = {
.timeout = 600s;
.interval = 10s;
.window = 5;
.threshold = 2;
.request = "GET HTTP/2"
"Host: https://www.example.com/index.html"
"Connection: close";
}
}

sudo systemctl 状态清漆:

Loaded: loaded (/etc/systemd/system/varnish.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2021-11-02 19:09:12 UTC; 1h 20min ago     
Docs: https://www.varnish-cache.org/docs/6.1/           
man:varnishd 
Main PID: 24668 (varnishd)    
Tasks: 217 (limit: 557)   
Memory: 12.1M   
CGroup: /system.slice/varnish.service           ├─24668 /usr/sbin/varnishd -j unix,user=vcache -F -a :80 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m           └─24680 /usr/sbin/varnishd -j unix,user=vcache -F -a :80 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m

Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Warnings:
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: VCL compiled.
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Debug: Version: varnish-6.0.8 revision 97e54ada6ac578af332e52b44d2038bb4fa4cd4a
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Debug: Platform: Linux,4.19.0-18-cloud-amd64,x86_64,-junix,-smalloc,-sdefault,-hcritbit
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Version: varnish-6.0.8 revision 97e54ada6ac578af332e52b44d2038bb4fa4cd4a
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Platform: Linux,4.19.0-18-cloud-amd64,x86_64,-junix,-smalloc,-sdefault,-hcritbit
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Debug: Child (24680) Started
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Child (24680) Started
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Info: Child (24680) said Child starts
Nov 02 19:09:12 ip-xxx-xx-xx-xx varnishd[24668]: Child (24680) said Child starts

sudo netstat -tlnp:

LISTEN  24668/varnishd      tcp 0   0 0.0.0.0:80    0.0.0.0:*       
LISTEN  13255/nginx: master tcp 0   00.0.0.0:8080   0.0.0.0:*
LISTEN  1352/sshd           tcp 0   00.0.0.0:22     0.0.0.0:*
LISTEN  24668/varnishd      tcp 0   0127.0.0.1:353210.0.0.0:*
LISTEN  13255/nginx: master tcp 0   00.0.0.0:443    0.0.0.0:*
LISTEN  537/trace-agent     tcp 0   0127.0.0.1:8126 0.0.0.0:*
LISTEN  536/agent           tcp 0   0127.0.0.1:5000 0.0.0.0:*
LISTEN  536/agent           tcp 0   0127.0.0.1:5001 0.0.0.0:*
LISTEN  13201/mysqld        tcp 0   0127.0.0.1:3306 0.0.0.0:*
LISTEN  589/redis-server 12 tcp 0   0127.0.0.1:6379 0.0.0.0:*
LISTEN  853/process-agent   tcp6 0  0127.0.0.1:6062 0.0.0.0:*
LISTEN  24668/varnishd      tcp6 0  0:::80          :::*
LISTEN  1352/sshd           tcp6 0  0:::22          :::*
LISTEN  589/redis-server 12 tcp6 0  0::1:6379       :::*

sudo apt-get install libwww-perl && GET -使用 http://localhost:80/index.html:

503 Backend fetch failed
Connection: close
Date: Tue, 02 Nov 2021 21:37:42 GMT
Via: 1.1 varnish (Varnish/6.0)
Age: 0
Retry-After: 5
Server: Varnish
Content-Length: 310
Content-Type: text/html; charset=utf-8
Client-Date: Tue, 02 Nov 2021 21:37:42 GMT
Client-Peer: 127.0.0.1:80
Client-Response-Num: 1
Title: 503 Backend fetch failed
X-Varnish: 32773

【问题讨论】:

    标签: nginx drupal varnish varnish-vcl


    【解决方案1】:

    请运行varnishlog -g raw -i backend_health 来监控您的后端运行状况并确定运行状况探测可能处于什么状态。

    基于此,您将了解 Varnish 为何返回 503 Backend fetch failed 错误。

    这很可能是因为您的探测中的 HTTP/2 请求。如果我没记错的话,Varnish 在后端不支持 HTTP/2,只在客户端支持。

    【讨论】:

    • 大量 0 Backend_health - 默认 仍然生病 4 --- X-R- 0 2 5 0.000198 0.000000 "" 和类似的。我尝试使用探针值,完全停用它(它甚至没有给我任何错误信号,但什么也没有,死了),我尝试使用 nginx 的值(例如通过停用 gzip ) 但没有,503 仍然存在。恐怕路还很长,不然我永远也找不到错在哪里。
    • @DantinoEsposito 尝试从 Nginx 虚拟主机配置中删除 http2 。如前所述:Varnish 不支持 HTTP/2 后端连接。
    • 当我删除 http2 时出现了一线希望,因为至少从那一刻起就提供了一个不愉快的答案,即 HTTP / 1.1 400 Bad Request 但确实存在。不幸的是,我仍然看不到 X-Varnish。使用来自 nginx 的 sudo cat error.log 它给了我 130 个客户端在读取客户端请求行时发送了无效请求,客户端:127.0.0.1,服务器:example.com,请求:“GET HTTP / 1.1”,而 access.log 给了我“GET HTTP /1.1“400 150”-“”-“”-“。我什至不记得对 nginx.conf 文件和相关块端口 443 做了多少更改,但 X-Varnish 只是一个希望。
    • @DantinoEsposito 为了清楚起见,您能否使用修改后的当前配置更新问题中的配置?我最初的预感是删除 VCL 后端探针中的 .request 属性,并将其替换为指向 /.url 属性。也许这会解决 VSL 输出中的 HTTP/1.1 400 Bad Request 问题。
    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 2016-04-20
    • 2016-01-17
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    相关资源
    最近更新 更多