HttpComponents HttpClient连接池(4)-连接的重用和KeepAlive


在 上一篇
文章里我们介绍了 httpclient 连接池中对于连接的申请和释放,这里我们主要介绍连接的重用,以及 keep alive。

http连接的重用


在 上一篇
文章 http 连接的释放中 ConnectionHolder的releaseConnection() 方法会根据是否重用有不同的处理,那么 ConnectionHolders 是如何决定是否重用呢。就在 MainClientExec类 的 execute() 方法里,核心代码如下

if (reuseStrategy.keepAlive(response, context)) {

// Set the idle duration of this connection

final long duration = keepAliveStrategy.getKeepAliveDuration(response, context);

if (this.log.isDebugEnabled()) {

final String s;

if (duration > 0) {

s = "for " + duration + " " + TimeUnit.MILLISECONDS;

} else {

s = "indefinitely";

}

this.log.debug("Connection can be kept alive " + s);

}

connHolder.setValidFor(duration, TimeUnit.MILLISECONDS);

connHolder.markReusable();

} else {

connHolder.markNonReusable();

}

分析以上代码的核心本质是调用 reuseStrategy的keepAlive() 方法来决定是否重用。reuseStrategy的值 在 HttpClientBuilder 进行构建 httpclient 连接池的默认值为 DefaultClientConnectionReuseStrategy ,核心代码如下:

public boolean keepAlive(final HttpResponse response, final HttpContext context) {

final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST);

if (request != null) {

final Header[] connHeaders = request.getHeaders(HttpHeaders.CONNECTION);

if (connHeaders.length != 0) {

final TokenIterator ti = new BasicTokenIterator(new BasicHeaderIterator(connHeaders, null));

while (ti.hasNext()) {

final String token = ti.nextToken();

if (HTTP.CONN_CLOSE.equalsIgnoreCase(token)) {

return false;

}

}

}

}

return super.keepAlive(response, context);

}

  • 分析如上代码,如果 http 请求的请求头中包含项 Connection:Close ,那么不重用。

  • 另外该方法还调用了父类的keepAlive() 方法,其父类是 DefaultConnectionReuseStrategy 类型,对父类 keep alive有下面分析。


  • 对于父类的逻辑中,如果 http 响应
    的响应头中包含项 Connection:Close ,那么不重用。



  • 对于父类的逻辑中,
    如果 http  响应


    响应


    中包含
    Transfer-Encoding ,但是如果它的值不为 chunked , 那么不重用



  • 对于父类的逻辑中,
    如果 响应状态码

    为204表示没有数据,但是响应头里Content-Length的值大于0或者不为数字,或者 http 响应头里有 
    Transfer-Encoding项 ,那么 不重用

http连接的Keep Alive

  • 在上面的 http 连接重用代码中我们不难发现,在确定重用的基础上, keep alive 的时间长短是由keepAliveStrategy的getKeepAliveDuration()方法所决定的。对于 keepAliveStrategy 实例, 在 HttpClientBuilder 进行构建 httpclient 时默认策略为 DefaultConnectionKeepAliveStrategy ,其核心代码如下:

public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {

Args.notNull(response, "HTTP response");

final HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));

while (it.hasNext()) {

final HeaderElement he = it.nextElement();

final String param = he.getName();

final String value = he.getValue();

if (value != null && param.equalsIgnoreCase("timeout")) {

try {

return Long.parseLong(value) * 1000;

} catch(final NumberFormatException ignore) {

}

}

}

return -1;

}

  • 通过分析上述代码,核心本质上是取得响应头 response header 项的 Keep-Alive: timeout 的值,单位为秒,如果没有那么取值-1。然后利用该值更新 CpoolEntry 对象的过期时间,如果该值为-1,则过期时间更新为Long.MAX_VALUE。

目前先写到这里,在下一篇文章里我们介绍 
http 连接的可用性检查。

HttpComponents HttpClient连接池(4)-连接的重用和KeepAlive

原文始发于微信公众号(TA码字): HttpComponents HttpClient连接池(4)-连接的重用和KeepAlive

原文 

https://www.javashitang.com/?p=530

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » HttpComponents HttpClient连接池(4)-连接的重用和KeepAlive

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址