Tomcat,HTTP Keep-Alive和Java的HttpsUrlConnection

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

要与安全服务器通信,代理上的servlet使用HttpsUrlConnection 。 我已经设置了WireShark,我注意到无论我在安全机器上为连接器设置了keepAliveTimeout值,TCP连接在大约5或10秒后关闭。 这个数字似乎与我所读到的是默认超时以及Java如何处理HTTP Keep-Alive。 此链接说明如果服务器发送了Java,则表示Keep-Alive超时,否则它在关闭连接之前使用5秒(直接连接)或10秒(代理连接)。

我想弄清楚的是我如何强制Tomcat发送Keep-Alive标头。 不, Connection: Keep-Alive ,但Keep-Alive: timeout=x

我已经尝试过使用Apache HTTP服务器并修改httpd.conf中的keepAliveTimeout会导致Keep-Alive标头更改其超时值。 此外,Java确实遵守此超时。

更新(12/23/11):在运行了几个实验之后,我尝试使用Apache的HttpClient(3.1)而不是HttpsUrlConnection编写一些快速而脏的代码。 看来HttpClient在设置为使用Keep-Alive时,只是等待服务器关闭连接。 我不知道它会等多久。 我正在拍摄以保持HTTP连接活动3到5分钟。

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

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

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

我通过WireShark确认这可以在客户端使用HttpUrlConnection。 如果您未设置“连接”标题,则它不起作用,因此您需要同时设置它们。

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

在这种情况下,您的代码必须完全读取缓冲区,关闭流并在IOException情况下读取错误。

当然HttpClient具有较少的约束,但处理您的情况的最佳方法是使用其MultiThreadedHttpConnectionManager这要归功于以下准则 。