You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Varnish仅根路径请求返回400错误,寻求技术排查方案

问题:Varnish仅根路径返回400错误,其余路径正常

部署的Varnish缓存服务器仅在访问站点根路径/(https://example.com/)时返回400 Bad Request错误,其余路径如example.com/en均可正常处理。

Varnish日志输出

*   << Request  >> 164200    
-   Begin          req 164199 rxreq
-   Timestamp      Start: 1676987476.561832 0.000000 0.000000
-   Timestamp      Req: 1676987476.561832 0.000000 0.000000
-   ReqStart       127.0.0.1 36702 a0
-   ReqMethod      GET
-   ReqURL         /
-   ReqProtocol    HTTP/1.0
-   ReqHeader      X-Real-IP: 10.254.27.52
-   ReqHeader      X-Forwarded-For: 10.254.27.52
-   ReqHeader      X-Forwarded-Proto: https
-   ReqHeader      X-Forwarded-Port: 443
-   ReqHeader      Connection: close
-   ReqUnset       X-Forwarded-For: 10.254.27.52
-   ReqHeader      X-Forwarded-For: 10.254.27.52, 127.0.0.1
-   VCL_call       RECV
-   ReqHeader      Surrogate-Capability: Varnish=ESI/1.0
-   ReqHeader      Host: 
-   ReqURL         /
-   VCL_return     hash
-   VCL_call       HASH
-   VCL_return     lookup
-   Hit            3 2414.934756 120.000000 0.000000
-   VCL_call       HIT
-   VCL_return     deliver
-   RespProtocol   HTTP/1.1
-   RespStatus     400
-   RespReason     Bad Request
-   RespHeader     Date: Tue, 21 Feb 2023 13:31:31 GMT
-   RespHeader     Server: Apache
-   RespHeader     Content-Length: 226
-   RespHeader     Content-Type: text/html; charset=iso-8859-1
-   RespHeader     x-url: /
-   RespHeader     x-host: 
-   RespHeader     X-Varnish: 164200 3
-   RespHeader     Age: 1185
-   RespHeader     Via: 1.1 varnish (Varnish/6.0)
-   VCL_call       DELIVER
-   RespUnset      x-url: /
-   RespUnset      x-host: 
-   RespUnset      Via: 1.1 varnish (Varnish/6.0)
-   RespUnset      X-Varnish: 164200 3
-   VCL_return     deliver
-   Timestamp      Process: 1676987476.561898 0.000066 0.000066
-   RespHeader     Connection: close
-   Timestamp      Resp: 1676987476.561937 0.000105 0.000040
-   ReqAcct        142 0 142 177 226 403
-   End     

TCP Dump捕获结果

TCP Dump捕获结果

varnishd服务配置

[Unit]
Description=Varnish Cache, a high-performance HTTP accelerator
After=network-online.target

[Service]
Type=forking
KillMode=process

# Maximum number of open files (for ulimit -n)
LimitNOFILE=131072

# Locked shared memory - should suffice to lock the shared memory log
# (varnishd -l argument)
# Default log size is 80MB vsl + 1M vsm + header -> 82MB
# unit is bytes
LimitMEMLOCK=85983232

# Enable this to avoid "fork failed" on reload.
TasksMax=infinity

# Maximum size of the corefile.
LimitCORE=infinity

ExecStart=/usr/sbin/varnishd -a :6081 -f /etc/varnish/default.vcl -s malloc,2g -p http_max_hdr=1024 -p http_resp_hdr_len=65536
ExecReload=/usr/sbin/varnishreload

[Install]
WantedBy=multi-user.target

问题原因分析

  1. 空Host头触发后端400:从日志可见请求的Host头为空(ReqHeader Host: ),后端Apache接收到无Host头的根路径请求时返回400错误。
  2. 错误响应被缓存:Varnish将这个400错误响应缓存,后续访问根路径时直接命中缓存返回错误,因此请求无需转发到后端Apache(与TCP Dump结果一致)。

解决办法

1. 立即清除根路径缓存条目

用varnishadm删除缓存的错误响应:

varnishadm ban req.url == "/"

2. 修改VCL配置避免重复问题

编辑/etc/varnish/default.vcl,在sub vcl_recv中添加以下逻辑二选一:

方案A:直接拦截空Host头请求

sub vcl_recv {
    // 拦截无Host头的请求,直接返回400
    if (req.http.Host == "") {
        return (synth(400, "Bad Request: Missing Host header"));
    }
    // 保留原有VCL逻辑...
}

方案B:允许空Host头但不缓存根路径

sub vcl_recv {
    // 空Host头的根路径请求直接透传到后端,不缓存
    if (req.url == "/" && req.http.Host == "") {
        return (pass);
    }
    // 保留原有VCL逻辑...
}

3. 重载Varnish配置

使修改后的配置生效:

systemctl reload varnish

内容的提问来源于stack exchange,提问作者Eng7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 15:10:16