连接池
高效的客户端HTTP传输通常要求高效的持久连接复用。HttpCore通过对管理持久化的HTTP连接提供支持,使连接复用的过程更方便。连接池的是现实是线程安全的,可以同时被多个消费者使用。
默认设置总共允许20个并发连接,每个路线上2个连接。这两项连接限制来自HTTP标准的要求。然而,在实际使用中这样的限制可能过于严格。可以根据具体应用场合,通过在运行时间修改连接池设置,来支持更多并发连接。
HttpHost target = new HttpHost("localhost");
BasicConnPool connpool = new BasicConnPool();
connpool.setMaxTotal(200);
connpool.setDefaultMaxPerRoute(10);
connpool.setMaxPerRoute(target, 20);
Future<BasicPoolEntry> future = connpool.lease(target, null);
BasicPoolEntry poolEntry = future.get();
HttpClientConnection conn = poolEntry.getConnection();
注意连接池无法知道已经释放给用户的连接是否还在使用。在不再需要连接时将连接交还给连接池是用户的责任,即使这个连接无法复用。
BasicConnPool connpool = <...>
Future<BasicPoolEntry> future = connpool.lease(target, null);
BasicPoolEntry poolEntry = future.get();
try {
HttpClientConnection conn = poolEntry.getConnection();
} finally {
connpool.release(poolEntry, true);
}
连接池状态可以在运行时间查看。
HttpHost target = new HttpHost("localhost");
BasicConnPool connpool = <...>
PoolStats totalStats = connpool.getTotalStats();
System.out.println("total available: " + totalStats.getAvailable());
System.out.println("total leased: " + totalStats.getLeased());
System.out.println("total pending: " + totalStats.getPending());
PoolStats targetStats = connpool.getStats(target);
System.out.println("target available: " + targetStats.getAvailable());
System.out.println("target leased: " + targetStats.getLeased());
System.out.println("target pending: " + targetStats.getPending());
注意,连接池不会主动去除过期连接。即使过期连接无法交给请求者,连接池仍然可能会积累过期连接,尤其是在一段时间没有任何活动之后。通常建议每隔一段时间不使用之后,强制去掉一些过期和仍在闲置的连接。
BasicConnPool connpool = <...>
connpool.closeExpired();
connpool.closeIdle(1, TimeUnit.MINUTES);
通常认为管理从连接池获取的连接,以及保证不再需要连接时立刻将连接交还连接池是用户的责任。但是BasicConnPool提供列举可用的闲置连接和已经从连接池中取走的连接。这使得连接池用户可以查询连接池状态,并在一定条件下选择性地关闭连接。
static class MyBasicConnPool extends BasicConnPool {
@Override
protected void enumAvailable(final PoolEntryCallback <HttpHost, HttpClientConnection> callback) {
super.enumAvailable(callback);
}
@Override
protected void enumLeased(final PoolEntryCallback<HttpHost, HttpClientConnection> callback) {
super.enumLeased(callback);
}
}
MyBasicConnPool connpool = new MyBasicConnPool();
connpool.enumAvailable(new PoolEntryCallback<HttpHost, HttpClientConnection>() {
@Override
public void process(final PoolEntry<HttpHost, HttpClientConnection> entry) {
Date creationTime = new Date(entry.getCreated());
if (creationTime.before(someTime)) {
entry.close();
}
}
});