Apache HttpComponents 连接池

核心类

AbstractConnPool

  • Lock lock 获取连接的是确保线程安全
  • ConnFactory connFactory 创建连接工厂
  • Map<T, RouteSpecificPool<T, C, E>> routeToPool 路由连接池
  • Set<E extends PoolEntry> leased 租借的连接
  • LinkedList<E extends PoolEntry> available 可用的连接entry集合
  • Map<T, Integer> maxPerRoute 每一个路由最大的连接数
  • LinkedList<PoolEntryFuture<E>> pending 等待处理的entry集合

PoolEntry类中包含route, conn, create(创建时间), validityDeadline(截止日期), update(更新时间), expiry(过期时间)。
在连接池中的,available是一个LinkedList类型,里面保存着可用PoolEntry对象,而PoolEntry对象中保存着连接的各种信息。

获取连接

连接池通过lease方法获取池的 entry,另外通过 entry 获取连接。

Future<BasicPoolEntry> future = pool.lease(this.target, null);
BasicPoolEntry entry = null;  
try {  
    entry = future.get();  
    HttpClientConnection connection = entry.getConnection();
} catch (InterruptedException e) {  
    e.printStackTrace();  
} catch (ExecutionException e) {  
    e.printStackTrace();  
}  

在获取连接时候,会做一下几步操作。

  • 判断是否获取连接超时
  • 通过 lock 锁住
  • 通过route获取到对应的pool
  • 遍历pool中的available是否存在state相同的连接, 如果存在将会在available中remove entry,增加到 lease链表中,表示租赁成功。
  • 如果不存在,在判断当前的连接是否超过maxPerRoute,如果没有超过,通过connFactory创建一个新的连接。如果超过,则放入pending链表中等待连接释放。
  • 释放锁

    释放连接

    通过 release(E entry, boolean reusable) 方法释放连接。步骤如下:

  • 通过lock锁住
  • 从lease链表中移除entry,通过reusable 字段是否放回到连接池中。
  • 如果 reusable 为 true,available通过addFirst放回池中。
  • 释放锁

另外AbstractNIOConnPool 原理类似。

简单用法

BasicConnPool connPool = new BasicConnPool();  
Future<BasicPoolEntry> lease = connPool.lease(host, null);  
BasicPoolEntry basicPoolEntry = lease.get();  
try {  
    HttpClientConnection connection = basicPoolEntry.getConnection();  
}finally {  
    connPool.release(basicPoolEntry, true);  
}
添加新评论