PoolingHttpClientConnectionManager原理剖析
继承体系
public class HttpClientUtil{
//全局参数
private PoolingHttpClientConnectionManager connectionManager;
//用来释放不用的连接 closeExpiredConnections() closeIdleConnections(long idletime, TimeUnit tunit)
private HttpClientConnectionMonitorThread thread;
//连接配置
private RequestConfig requestConfig;
//单例模式创建资源
@PostConstruct
private void init() {//bean初始化
if (connectionManager == null) {
connectionManager = new PoolingHttpClientConnectionManager();
// 整个连接池最大连接数
connectionManager.setMaxTotal(MAX_TOTAL);
// 每路由最大连接数,默认值是2
connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
/** 管理 http连接池 */
thread = new HttpClientConnectionMonitorThread(connectionManager);
requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(REQ_TIMEOUT)
.setConnectTimeout(CONN_TIMEOUT).setSocketTimeout(SOCK_TIMEOUT)
.build();
}
}
//下次获取httpClient的时候是这样的
public CloseableHttpClient getHttpClient() {
return HttpClients.custom().setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig).build();
}
}
/**
* @ClassName: HttpClientConnectionMonitorThread
* @Description: TODO(使用管理器,管理HTTP连接池 无效链接定期清理功能)
* @author xiangqi
* @date 2018-01-29 下午 2:10
*/
public class HttpClientConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connManager;
private volatile boolean shutdown = false;
public HttpClientConnectionMonitorThread(HttpClientConnectionManager connManager) {
super();
this.setName("http-connection-monitor");
this.setDaemon(true);
this.connManager = connManager;
this.start();
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
// 等待5秒
wait(5000);
// 关闭过期的链接
connManager.closeExpiredConnections();
// 选择关闭 空闲30秒的链接
connManager.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
//ignore ex
}
}
}
连接是如何租用和释放的?
创建CloseableHttpClient时,一个重要的方法是HttpClientBuilder#build():CloseableHttpClient。发现源码里面都是初始化以下函数的入参:
public InternalHttpClient(
final ClientExecChain execChain,
final HttpClientConnectionManager connManager,
final HttpRoutePlanner routePlanner,
final Lookup<CookieSpecProvider> cookieSpecRegistry,
final Lookup<AuthSchemeProvider> authSchemeRegistry,
final CookieStore cookieStore,
final CredentialsProvider credentialsProvider,
final RequestConfig defaultConfig,
final List<Closeable> closeables) {
super();
Args.notNull(execChain, "HTTP client exec chain");
Args.notNull(connManager, "HTTP connection manager");
Args.notNull(routePlanner, "HTTP route planner");
this.execChain = execChain;
this.connManager = connManager;
this.routePlanner = routePlanner;
this.cookieSpecRegistry = cookieSpecRegistry;
this.authSchemeRegistry = authSchemeRegistry;
this.cookieStore = cookieStore;
this.credentialsProvider = credentialsProvider;
this.defaultConfig = defaultConfig;
this.closeables = closeables;
}
获取连接,回收连接触发时机
CloseableHttpClient#execute( HttpUriRequest request):CloseableHttpResponse,断点调试发现,其实底层调用的是
- InternalHttpClient#doExecute( HttpHost , HttpRequest ,HttpContext )
- this.execChain.execute(route, wrapper, localcontext, execAware)
- MainClinetExec#execute*(HttpRoute,HttpRequestWrapper,HttpClientContext,HttpExecutionAware)
- HttpClientConnectionManager#requestConnection(HttpRoute,Object):ConnectionRequest
- ConnectionRequest#get(long,TimeUnit):HttpClientConnection
,这就是租用时机
- CloseableHttpResponse#close()
,这是回收链接时机
- ConnectionHolder#close()
- ConnectionHolder#releaseConnection()
- releaseConnection$releaseConnection(boolean)