在阅读了Apache HTTP组件模块的连接管理文档以及其他一些关于连接保持有效策略和连接驱逐策略的资源后,我感到非常困惑。
其中有一堆形容词用于描述连接的状态,如stale
、idle
、available
、expired
和closed
等。没有描述连接在这些状态之间如何变化的生命周期图。
我的困惑主要源于以下情况。
我通过下面的代码片段设置了一个ConnectionKeepAliveStrategy
,它提供5秒的KeepAliveDuration
。
ConnectionKeepAliveStrategy keepAliveStrategy = ( httpResponse, httpContext ) -> {
HeaderElementIterator iterator =
new BasicHeaderElementIterator( httpResponse.headerIterator( HTTP.CONN_KEEP_ALIVE ) );
while ( iterator.hasNext() )
{
HeaderElement header = iterator.nextElement();
if ( header.getValue() != null && header.getName().equalsIgnoreCase( "timeout" ) )
{
return Long.parseLong( header.getValue(), 10) * 1000;
}
}
return 5 * 1000;
};
this.client = HttpAsyncClients.custom()
.setDefaultRequestConfig( requestConfig )
.setMaxConnTotal( 500 )
.setMaxConnPerRoute( 500 )
.setConnectionManager( this.cm )
.setKeepAliveStrategy( keepAliveStrategy )
.build();
与我交谈的服务器确实支持保持连接的有效性。当我在一批中异步执行大约200个请求后打印出连接管理器的池统计数据时,观察到了以下信息。
Total Stats:
-----------------
Available: 139
Leased: 0
Max: 500
Pending: 0
在等待了30秒之后(那时已经超过了保持活动超时(,我开始了一批相同的HTTP调用。在检查连接管理器池统计数据时,可用连接的数量仍然是139。
既然达到了保活超时,它不应该是零吗PoolStats Java文档声明CCD_;空闲持久连接的数量";。空闲的持久连接是否被认为是活动的?
我认为Apache HttpClient:如何通过服务器的保持活动时间自动关闭连接是一个热门话题,但希望一些专家能对PoolingHttpClientConnectionManager
管理的连接的生命周期做出有见地的解释。
其他一些一般性问题:
HttpAsyncClients.createdDefault()
中使用的默认连接管理器是否单独处理连接保持活动策略和连接驱逐- 在自定义的基础上实现它们的要求/限制是什么?他们会互相矛盾吗
记录我的一些进一步发现,这些发现可能会部分实现。
-
无论是否使用
ConnectionKeepAliveStrategy
在保持活动会话上设置超时,连接都将最终处于ESTABLISHED
的TCP状态,如通过netstat -apt
检查的那样。我观察到,在我的Linux测试环境中,它们在大约5分钟后会自动回收。 -
当不使用
ConnectionKeepAliveStrategy
时,在第二次请求批处理时,已建立的连接将被重用。 -
当使用
ConnectionKeepAliveStrategy
并且尚未达到其超时时,在第二次请求批处理时,已建立的连接将被重用。 -
当使用
ConnectionKeepAliveStrategy
并超过其超时时,在第二次请求批处理时,已建立的连接将被回收到TIME_WAIT
状态,表明客户端已决定关闭连接。 -
这种回收可以通过在单独的连接驱逐线程中执行
connectionManager.closeExpiredConnections();
来主动执行,这将导致连接进入TIME_WAIT
阶段。
我认为一般的观察结果是,连接池统计数据将ESTABLISHED
连接视为Available
,带有超时的连接保持活动策略确实会使连接过期,但它只有在处理新请求时,或者当我们特别指示连接管理器关闭过期连接时才生效。
TCP状态图来自维基百科以供参考。