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
这要归功于以下准则 。
- “java.lang.IllegalStateException:在建立连接后无法设置请求属性”在Android中出错
- 在Java中,有多接近连接并使用HttpURLConnection释放端口/套接字?
- validationCXF HttpAsyncClient使用use.async.http.conduit上下文属性
- 如何防止来自HttpsURLConnection的CONNECT方法调用
- 获取对Java的默认http(s)URLStreamHandler的引用
- 所有信任的HostnameVerifier都会导致HttpURLConnection出现SSL错误
- HttpURLConnection实现
- -POST Json with HttpUrlConnection
- Java HTTPUrlConnection超时不起作用