我有两台Tomcat服务器需要维持持久连接以减少SSL握手。一台服务器(代理)位于DMZ中,而另一台服务器安全地位于另一台防火墙后面。代理基本上只运行一个简单的servlet,在将请求转发到安全机器之前进行一些健全性检查。在初始请求中,机器在执行实际工作之前交换证书。因此,我希望在几分钟的超时时间内保持持久连接。
要与安全服务器通信,代理上的servlet使用HttpsUrlConnection
。我已经设置了WireShark,我注意到无论我在安全机器上为连接器设置了什么keepAliveTimeout
值,TCP连接在大约5或10秒后关闭。这个数字似乎与我所读到的是默认超时以及Java如何处理HTTP Keep-Alive。这个link解释说,如果服务器发送了Java,{@ 1}}超时,否则它会在关闭连接之前使用5秒(直接连接)或10秒(代理连接)。
我想弄清楚的是如何强制Tomcat发送Keep-Alive标头。不是Keep-Alive
,而是Connection: Keep-Alive
。
我已经尝试过Apache HTTP服务器并修改httpd.conf中的Keep-Alive: timeout=x
会导致Keep-Alive标头更改其超时值。此外,Java确实遵守此超时。
更新(12/23/11):在运行了几个实验后,我尝试使用Apache的HttpClient(3.1)而不是keepAliveTimeout
来编写一些快速而脏的代码。看来HttpClient在设置为使用Keep-Alive时,只是等待服务器关闭连接。我不知道它会等多久。我正在拍摄以保持HTTP连接活动3到5分钟。
答案 0 :(得分:8)
我可以使用HttpClient 3.1通过将Tomcat连接器中的keepAliveTimeout设置为300000来保持HTTP连接打开5分钟。我使用WireShark验证了服务器将终止连接,而HttpClient只是等待。通过HttpClient的后续请求重用现有的TCP连接(避免任何进一步的SSL握手)。但关键是要有一个HttpClient实例(即每次都不创建一个)。这对大多数人来说可能是显而易见的,但我不确定HTTPClient的API机制是什么。简而言之,创建一个HttpClient实例,并为每个请求(POST,GET等)创建一个新的PostMethod,GetMethod等。这将导致重用TCP连接。
答案 1 :(得分:5)
在Tomcat中,我设法使用HttpServletResponse.addHeader()在我的HttpServelet中设置标题:
response.addHeader("Connection", "Keep-Alive");
response.addHeader("Keep-Alive", "timeout=60000");
我与WireShark确认这可以在客户端使用HttpUrlConnection。如果您没有设置“连接”标题,则它不起作用,因此您需要同时设置它们。
答案 2 :(得分:2)
Java API Http(s)UrlConnection
无缝地尊重Keep-Alive
信息,并根据following detailed explanation管理每个服务器主机的连接池(仔细阅读 - 每个细节都很重要)。
在这种情况下,如果IOException
,您的代码必须完全读取缓冲区,关闭流和读取错误。
当然HttpClient的约束较少,但处理您情况的最佳方法是使用MultiThreadedHttpConnectionManager
来使用following guidelines。