Varnish缓存随机改变响应内容长度

Varnish缓存随机改变响应内容长度

我有一个系统通过四个负载平衡的 varnish 缓存访问多个后端服务。大约 0.1% 的请求被截断,因为 varnish 返回了不正确的内容长度标头。此错误发生在所有缓存和各种后端。

Varnish 配置为不缓存任何没有有效缓存控制标头的内容,并且不会缓存这些特定请求。客户端不会发送 Accept-Encoding 标头,因此 Varnish 会从后端请求经过 gzip 压缩的响应,并向客户端发送未压缩的版本。

从 varnishlog 来看,所有后端请求看起来都一样:

BerespStatus   200
BerespReason   OK
BerespHeader   Content-Encoding: gzip
BerespHeader   Content-Length: 1001
BerespHeader   Content-Type: application/json
BerespHeader   Date: Fri, 08 Feb 2019 14:59:06 GMT
BerespHeader   Vary: Accept-Encoding
TTL            RFC 0 10 0 1549637947 1549637947 1549637946 0 0 cacheable
VCL_call       BACKEND_RESPONSE
TTL            VCL 120 10 0 1549637947 cacheable
TTL            VCL 120 10 0 1549637947 uncacheable
VCL_return     deliver
Filters        testgunzip
Storage        malloc Transient
Fetch_Body     3 length stream
Gzip           u F - 1001 3792 80 7906 7944
BackendReuse   54 default
Length         1001

我相信该行Gzip u F - 1001 3792 80 7906 7944表明 1001 字节的压缩响应解压缩后为 3792 字节。

有三种不同类型的响应。约 50% 将内容长度设置为 3792:

VCL_call       RECV
ReqHeader      Surrogate-Capability: key=ESI/1.0
VCL_return     hash
VCL_call       HASH
VCL_return     lookup
HitMiss        1052359 119.885211
VCL_call       MISS
VCL_return     fetch
Link           bereq 1052362 fetch
Timestamp      Fetch: 1549633459.720553 0.004765 0.004765
RespProtocol   HTTP/1.1
RespStatus     200
RespReason     OK
RespHeader     Content-Encoding: gzip
RespHeader     Content-Length: 1000
RespHeader     Content-Type: application/json
RespHeader     Date: Fri, 08 Feb 2019 13:44:19 GMT
RespHeader     Vary: Accept-Encoding
RespHeader     Age: 0
RespHeader     Via: 1.1 varnish (Varnish/6.1)
VCL_call       DELIVER
RespHeader     X-Cache: MISS
RespHeader     X-Cache-Hits: 0
VCL_return     deliver
Timestamp      Process: 1549633459.720567 0.004779 0.000014
RespUnset      Content-Encoding: gzip
RespHeader     Accept-Ranges: bytes
RespUnset      Content-Length: 1000
RespHeader     Content-Length: 3792
Gzip           U D - 1001 3792 80 7906 7944

大约 50% 没有内容长度标头,但使用传输编码分块:

Same as above except
...
RespUnset      Content-Length: 1000
RespHeader     Transfer-Encoding: chunked
Gzip           U D - 1001 3792 80 7906 7944

还有 0.1% 的情况是因为内容长度不正确而导致客户端崩溃:

...
RespUnset      Content-Length: 1001
RespHeader     Content-Length: 208
Gzip           U D - 1001 3792 80 7906 7944

有人知道造成这种情况的原因吗?对调试的下一步有什么建议吗?

我的 VCL 不对内容长度标头执行任何操作。我正在运行 varnish 6.1(我正在考虑降级到稳定版本 6.0.2,但尚未尝试)


编辑:

降级到 6.0.2 并且仍然看到同样的问题。


编辑2:

我已经使用命令开关禁用了 varnish 将请求升级到 gzip -p "http_gzip_support=off",这样就解决了这个问题,但代价是非压缩请求在到达后端时仍然不是压缩的,但现在这样已经足够了。

相关内容