对 Cookie 大小导致的 500 错误进行故障排除
Troubleshooting 500 Error Due to Cookie Size
网站访问者在浏览一段时间后收到 500 内部服务器错误,这是由于跟踪 cookie 将我们域的整体 cookie 大小推到超过 4kb(这是一个页面浏览 cookie,所以它每次都会附加页面名称你访问了一个新页面)。
我可以使用带有非常大的 cookie 负载的 curl 重现该问题。在这样做的过程中,我已经能够验证 500 的确切来源(我们从 Cloudflare 到 Varnish 再到后端网络服务器)。我已经验证失败的请求不会到达网络服务器,所以我相信 Varnish 是服务于 500s 的那个。我也看过 varnishlog 并看到 500s 出现了。
这是来自 varnishlog 的示例响应
-- VCL_return hash
-- VCL_call HASH
-- VCL_return lookup
-- Hit 57254162
-- VCL_call HIT
-- VCL_return deliver
-- RespProtocol HTTP/1.1
-- RespStatus 200
-- RespReason OK
-- RespHeader X-Powered-By: Express
-- RespHeader Date: Thu, 01 Aug 2019 23:05:52 GMT
-- RespHeader Content-Type: application/json; charset=utf-8
-- RespHeader Content-Length: 1174
-- RespHeader X-Varnish: 57156196 57519178
-- RespHeader Age: 86
-- RespHeader Via: 1.1 varnish-v4
-- VCL_call DELIVER
-- RespHeader X-Cache: HIT
-- RespUnset X-Powered-By: Express
-- VCL_return deliver
-- Timestamp Process: 1564700838.564547 0.000354 0.000354
-- RespHeader Accept-Ranges: bytes
-- Debug "RES_MODE 2"
-- RespHeader Connection: keep-alive
-- Error workspace_client overflow
-- RespProtocol HTTP/1.1
-- RespStatus 500
-- RespReason Internal Server Error
-- Timestamp Resp: 1564700838.564580 0.000387 0.000033
-- ReqAcct 10063 0 10063 0 0 0
-- End
这是我添加到 vcl_recv 部分以删除违规 cookie 的内容
set req.http.Cookie = regsuball(req.http.Cookie, "_loc_[^;]+(; )?", "");
我不明白这里的两个 RespStatus 条目有什么意义。为什么是200,然后是500?我还注意到,如果我使用使用 HTTP/1.1 的 curl,我会得到 500,但是如果我使用使用 HTTP/2 的 HTTPie,我会得到 200。这是预期的吗? Varnish 会根据 http 版本以不同方式处理 cookie 大小吗?
*编辑:我想我已经弄清楚了两种响应状态的区别在于,一种是将内容传递给清漆,第二种是将内容传递给客户端。
正如日志所说,工作量space 太小无法容纳事务(headers,特别是),请尝试增加它:
varnishadm param.set workspace_client 128k
详细解释:varnish 对每笔交易使用 "worspace"。这是一块用于分配数据的内存,整个块在事务结束时被擦除。 header特别是被复制到作品space中,每次添加或修改一个header,它也会去那里。
这里的问题是你没有足够的space。早期版本只会恐慌,但现在更智能,只会产生状态为 500 的综合响应。诀窍在于它在复制初始响应后意识到缺少 workspace,因此您会在日志中看到这两个响应。
网站访问者在浏览一段时间后收到 500 内部服务器错误,这是由于跟踪 cookie 将我们域的整体 cookie 大小推到超过 4kb(这是一个页面浏览 cookie,所以它每次都会附加页面名称你访问了一个新页面)。
我可以使用带有非常大的 cookie 负载的 curl 重现该问题。在这样做的过程中,我已经能够验证 500 的确切来源(我们从 Cloudflare 到 Varnish 再到后端网络服务器)。我已经验证失败的请求不会到达网络服务器,所以我相信 Varnish 是服务于 500s 的那个。我也看过 varnishlog 并看到 500s 出现了。
这是来自 varnishlog 的示例响应
-- VCL_return hash
-- VCL_call HASH
-- VCL_return lookup
-- Hit 57254162
-- VCL_call HIT
-- VCL_return deliver
-- RespProtocol HTTP/1.1
-- RespStatus 200
-- RespReason OK
-- RespHeader X-Powered-By: Express
-- RespHeader Date: Thu, 01 Aug 2019 23:05:52 GMT
-- RespHeader Content-Type: application/json; charset=utf-8
-- RespHeader Content-Length: 1174
-- RespHeader X-Varnish: 57156196 57519178
-- RespHeader Age: 86
-- RespHeader Via: 1.1 varnish-v4
-- VCL_call DELIVER
-- RespHeader X-Cache: HIT
-- RespUnset X-Powered-By: Express
-- VCL_return deliver
-- Timestamp Process: 1564700838.564547 0.000354 0.000354
-- RespHeader Accept-Ranges: bytes
-- Debug "RES_MODE 2"
-- RespHeader Connection: keep-alive
-- Error workspace_client overflow
-- RespProtocol HTTP/1.1
-- RespStatus 500
-- RespReason Internal Server Error
-- Timestamp Resp: 1564700838.564580 0.000387 0.000033
-- ReqAcct 10063 0 10063 0 0 0
-- End
这是我添加到 vcl_recv 部分以删除违规 cookie 的内容
set req.http.Cookie = regsuball(req.http.Cookie, "_loc_[^;]+(; )?", "");
我不明白这里的两个 RespStatus 条目有什么意义。为什么是200,然后是500?我还注意到,如果我使用使用 HTTP/1.1 的 curl,我会得到 500,但是如果我使用使用 HTTP/2 的 HTTPie,我会得到 200。这是预期的吗? Varnish 会根据 http 版本以不同方式处理 cookie 大小吗?
*编辑:我想我已经弄清楚了两种响应状态的区别在于,一种是将内容传递给清漆,第二种是将内容传递给客户端。
正如日志所说,工作量space 太小无法容纳事务(headers,特别是),请尝试增加它:
varnishadm param.set workspace_client 128k
详细解释:varnish 对每笔交易使用 "worspace"。这是一块用于分配数据的内存,整个块在事务结束时被擦除。 header特别是被复制到作品space中,每次添加或修改一个header,它也会去那里。
这里的问题是你没有足够的space。早期版本只会恐慌,但现在更智能,只会产生状态为 500 的综合响应。诀窍在于它在复制初始响应后意识到缺少 workspace,因此您会在日志中看到这两个响应。