首页 > 解决方案 > Tomcat 偶尔会返回没有 HTTP 标头的响应

问题描述

我正在调查 Tomcat ( 7.0.90 7.0.92) 偶尔返回没有 HTTP 标头的响应的问题。

根据Wireshark抓包,Tomcat收到请求后,只返回一个响应体。它既不返回状态行也不返回 HTTP 响应标头。

它使下游的 Nginx 实例产生错误“upstream sent no valid HTTP/1.0 header while reading response header from upstream”,向客户端返回 502 错误并关闭 Nginx 和 Tomcat 之间相应的 http 连接。

这种行为的原因可能是什么?是否有任何可能使 Tomcat 以这种方式运行?或者在某些情况下可能有一些东西会去除 HTTP 标头?或者 Wireshark 未能捕获包含 HTTP 标头的帧?任何缩小问题范围的建议也非常感谢。

这是 Wireshark 的“Follow HTTP Stream”的屏幕截图,显示了有问题的响应:

在此处输入图像描述

编辑:

这是相关部分的“TCP Stream”的屏幕截图(仅响应)。似乎最后一个响应中的第二个块看起来不错:

在此处输入图像描述

编辑2:

我将此问题转发到 Tomcat 用户邮件列表,并从开发人员那里得到了一些进一步调查的建议:

http://tomcat.10.x6.nabble.com/Tomcat-occasionally-returns-a-response-without-HTTP-headers-td5080623.html

但我还没有找到任何合适的解决方案。我仍在寻找解决此问题的见解..

标签: httptomcatnginxjava-metro-frameworkchunked

解决方案


您遇到的问题源于通过与上游的单个连接对多个请求进行管道传输,正如Eugène Adell昨天的回答所解释的那样。

无论这是 nginx、tomcat、您的应用程序中的错误,还是上述任何组合的交互,都可能是另一个论坛的讨论,但现在,让我们考虑什么是最好的解决方案:

你可以发布你的nginx配置吗?具体来说,如果您正在使用nginxkeepalive中的非默认值?proxy_http_version– cnst 1 小时前

@cnst 我正在使用proxy_http_version 1.1keepalive 100– Kohei Nozaki 1 小时前

根据SO 上一个不相关问题的较早答案,但如上所述共享配置参数,您可能需要重新考虑在前端负载均衡器(例如,nginx)和后端应用服务器(例如,tomcat)。

根据nginx 上下文中关于 ServerFault 的 keepalive 解释,upstream直到最近在 nginx 开发年代,才支持 nginx 上下文中的 keepalive 功能。为什么?这是因为当建立新连接比等待现有连接可用时基本上更快时,使用 keepalive 的有效场景很少:

  • 当客户端和服务器之间的延迟大约为 50 毫秒+时,keepalive 可以重用 TCP 和 SSL 凭据,从而显着提高速度,因为不需要额外的往返来使连接准备好为 HTTP 提供服务要求。

    这就是为什么你永远不应该禁用客户端和 nginx 之间的 keepalive(通过http://nginx.org/r/keepalive_timeout 和上下文控制)。httpserverlocation

  • 但是当前端代理服务器和后端应用服务器之间的延迟在 1 毫秒(0.001 秒)的数量级时,使用keepalive是一种追逐黑森虫的秘诀,而不会获得任何好处,因为建立连接的额外 1 毫秒延迟可能是小于等待现有连接可用的 100 毫秒延迟。keepalive(这是对连接处理的过度简化,但它只是向您展示了前端负载均衡器和应用程序服务器之间的任何可能的好处是多么微不足道,前提是它们都位于同一区域。)

    这就是为什么在上下文中使用http://nginx.org/r/keepaliveupstream很少是一个好主意,除非你真的需要它,并且已经特别验证了它会产生你想要的结果,鉴于上述几点。

    (而且,为了清楚起见,这些要点与您使用的实际软件无关,因此,即使您没有遇到使用 nginx 和 tomcat 组合时遇到的问题,我仍然建议您不要即使您决定从 nginx 和 tomcat 中的一个或两个切换,也要在负载均衡器和应用程序服务器之间使用 keepalive。)


我的建议?


推荐阅读