我正在更新旧项目的依赖项。引入的传递性更改之一是
apache-httpclient
从 4.5 到 5.2 的版本提升。该项目实现了 4.5.x 教程第 2 章连接管理第 5 节连接驱逐策略中推荐的
IdleConnectionMonitorThread
,其中表示:
经典阻塞 I/O 模型的主要缺点之一是网络套接字只有在 I/O 操作中被阻塞时才能对 I/O 事件做出反应。当连接被释放回管理器时,它可以保持活动状态,但无法监视套接字的状态并对任何 I/O 事件做出反应。如果连接在服务器端关闭,则客户端连接无法检测到连接状态的变化(并通过关闭其一端的套接字来做出适当的反应)。
HttpClient 尝试通过测试连接是否“过时”来缓解问题,该连接在使用连接执行 HTTP 请求之前已在服务器端关闭,因此不再有效。过时连接检查并非 100% 可靠。不涉及空闲连接的每套接字一个线程模型的唯一可行解决方案是专用监视器线程,用于逐出由于长时间不活动而被视为过期的连接。监视器线程可以定期调用 ClientConnectionManager#closeExpiredConnections() 方法来关闭所有过期连接,并从池中驱逐已关闭的连接。它还可以选择调用 ClientConnectionManager#closeIdleConnections() 方法来关闭在给定时间段内空闲的所有连接。
public static class IdleConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
super();
this.connMgr = connMgr;
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(5000);
// Close expired connections
connMgr.closeExpiredConnections();
// Optionally, close connections
// that have been idle longer than 30 sec
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
// terminate
}
}
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}
之前有一个问题Commons Components HttpClient IdleConnectionMonitorThread需要吗?探索
当 HttpClientConnectionManager 的两个实现(PoolingHttpClientConnectionManager 和 BasicHttpClientConnectionManager)都有关闭旧连接的逻辑时,为什么推荐[这个]?
但是,仅限于httpclient-4.x的上下文。我注意到 Apache v5.x 的文档不包含教程,并且在
快速入门指南中的任何位置都没有引用
IdleConnectionMonitorThread
,也没有从 4.x 指南迁移。
那么是否仍然建议定期清除空闲和陈旧的连接?或者 v5.x 的内部是否隐藏着一些东西,可以以 4.x 没有/不能的方式自动管理此操作?更广泛地说,是否有关于我缺少的 4.x 教程范围的 v5.x 官方 Apache 教程?
经典 Java(阻塞)I/O 的限制是,只有当底层套接字在读/写操作中被阻塞时才能够对 I/O 事件做出反应,这一限制适用于 Apache HttpClient 的所有版本以及基于经典 I/O API。
连接池中保留的空闲客户端连接无法对对方端点关闭其一端的连接做出反应。监视池中的连接并主动删除那些闲置时间过长的连接可能仍然是有益的。