Tomcat、HTTP Keep-Alive 和 Java 的 HttpsUrlConnection

问题描述 投票:0回答:4

我有两个 Tomcat 服务器需要保持持久连接以减少 SSL 握手。一台服务器(代理)位于 DMZ 中,而另一台服务器安全地位于另一个防火墙后面。代理基本上只是运行一个简单的 servlet,它在将请求转发到安全机器之前进行一些健全性检查。根据初始请求,机器在执行实际工作之前交换证书。因此,我想保持几分钟超时的持久连接。

为了与安全服务器对话,代理上的 servlet 使用

HttpsUrlConnection
。我已经设置了 WireShark,我注意到无论我为安全机器上的连接器设置什么
keepAliveTimeout
值,TCP 连接都会在大约 5 或 10 秒后关闭。这个数字似乎与我读到的默认超时以及 Java 如何处理 HTTP Keep-Alive 相符。这个 link 解释说,如果 Java 由服务器发送超时,它会遵守
Keep-Alive
超时,否则它会在关闭连接之前使用 5 秒(直接连接)或 10 秒(代理连接)。

我想弄清楚的是如何强制 Tomcat 发送 Keep-Alive 标头。不是,

Connection: Keep-Alive
,而是
Keep-Alive: timeout=x
.

我已经尝试使用 Apache HTTP 服务器并修改 httpd.conf 中的

keepAliveTimeout
确实会导致 Keep-Alive 标头更改其超时值。此外,Java 确实遵守此超时。

更新(2011 年 12 月 23 日): 在进行了更多实验后,我尝试使用 Apache 的 HttpClient (3.1) 而不是

HttpsUrlConnection
编写一些快速而肮脏的代码。似乎 HttpClient 在设置为使用 Keep-Alive 时只是等待服务器关闭连接。虽然不知道要等多久。我打算让 HTTP 连接保持 3 到 5 分钟。

java tomcat httpurlconnection keep-alive
4个回答
8
投票

通过将 Tomcat 连接器中的 keepAliveTimeout 设置为 300000,我能够使用 HttpClient 3.1 将 HTTP 连接保持打开状态 5 分钟。我使用 WireShark 验证了服务器将终止连接,而 HttpClient 将只是等待。通过 HttpClient 的后续请求会重用现有的 TCP 连接(避免任何进一步的 SSL 握手)。那里的关键是有一个 HttpClient 实例(即不是每次都创建一个)。这对大多数人来说可能是显而易见的,但我不确定 HTTPClient 的 API 机制是什么。简而言之,创建一个 HttpClient 实例并为每个请求(POST、GET 等)创建一个新的 PostMethod、GetMethod 等。这将导致 TCP 连接被重用。


6
投票

在 Tomcat 中,我设法使用 HttpServletResponse.addHeader() 在我的 HttpServelet 中设置标头,如下所示:

  response.addHeader("Connection", "Keep-Alive");
  response.addHeader("Keep-Alive", "timeout=60000");

我向 WireShark 确认这确实适用于客户端的 HttpUrlConnection。如果你不设置“连接”头,它就不起作用,所以你需要同时设置。


2
投票

Java API

Http(s)UrlConnection
无缝地尊重
Keep-Alive
信息并根据 以下详细解释(仔细阅读 - 每个细节都很重要)管理每个服务器主机的连接池。

在那种情况下,您的代码必须完全读取缓冲区,关闭流并在

IOException
的情况下读取错误。

当然,HttpClient 的限制较少,但处理您的情况的最佳方法是使用它的

MultiThreadedHttpConnectionManager
,这要归功于以下指南


0
投票

如果您可以将第一个(外部)服务器升级到 Java 19 或更高版本,则可以使用此 Java 系统属性,它在服务器未指定时设置客户端保持活动时间:

http.keepAlive.time.server=60

默认为 5 秒。以上将其设置为 1 分钟。在连接的客户端将其更改为更高的值将解决您的问题(注意:仅适用于 Java 19 及更高版本)。

© www.soinside.com 2019 - 2024. All rights reserved.