前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >HttpComponents HttpClient连接池(9)-长连接

HttpComponents HttpClient连接池(9)-长连接

作者头像
TA码字
发布于 2020-04-14 03:44:01
发布于 2020-04-14 03:44:01
1.6K00
代码可运行
举报
文章被收录于专栏:TA码字TA码字
运行总次数:0
代码可运行

上一篇文章里我们介绍了 httpclient 连接池对于 SSL 的支持,这里主要介绍连接池中的长连接。

根据以前文章, 对于httpclient 连接池中的池化对象 CpoolEntry 都是可以被复用的,这样在每次申请连接的时候都会从可用连接集合 available 中获取,避免每次都重新创建连接,提高了效率。关于连接池如何决定重用连接,以及连接 keep alive 保活多久的介绍,请参考这篇文章。池化对象 CpoolEntry 虽然重用了,但是里面真正的原始 socket 是长连接么?我们从使用 httpclient 的代码分析,一般使用 httpclient 的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*Application code*/
try {
      CloseableHttpClient htttpClient = HttpClients.custom().build();
      HttpGet getMethod = new HttpGet("https://www.baidu.com/");
      CloseableHttpResponse response = htttpClient.execute(getMethod);
      HttpEntity entitry = response.getEntity();
      byte[] contentArray = EntityUtils.toByteArray(entitry);
 } catch (Exception e) {
        // TODO Handle Exception here
 }

/*EntityUtils*/
public static byte[] toByteArray(final HttpEntity entity) throws IOException {
    Args.notNull(entity, "Entity");
    final InputStream inStream = entity.getContent();
    if (inStream == null) {
       return null;
    }
    try {
        Args.check(entity.getContentLength() <= Integer.MAX_VALUE, "HTTP entity too large to be buffered in memory");
        int capacity = (int)entity.getContentLength();
        if (capacity < 0) {
            capacity = DEFAULT_BUFFER_SIZE;
        }
        final ByteArrayBuffer buffer = new ByteArrayBuffer(capacity);
        final byte[] tmp = new byte[DEFAULT_BUFFER_SIZE];
        int l;
        while((l = inStream.read(tmp)) != -1) {
            buffer.append(tmp, 0, l);
        }
        return buffer.toByteArray();
    } finally {
        inStream.close();
    }
}
  • 根据上述代码在调用 EntityUtils.toByteArray() 方法的时候,会最终调用 inputStream 的 close() 方法。
  • 我们 debug 调试原始代码的 inputStream 对象实例的 close() 方法。
  • 通过上述调试我们发现,最终调用了 ConnectionHolder 对象的 releaseConnection() 方法,而且是重用连接的,根据以前文章, releaseConnection() 方法在重用 connection 的情况下只是把池化对象 CpoolEntry 分别在 global 连接池和 route 的 individual 连接池的正在使用集合 leased 中移除,并加入各自的可用连接集合 available 中,并没有对原始 socket 关闭,所以是 http 长连接。
  • 另外通过上述源码分析,和 EntityUtils 对象实例的 toByteArray() 方法一样, EntityUtils 对象的 toString(), consume(), consumeQuietly() 等方法也是在 finally 块里调用了 inputStream 的 close() 方法,从而间接的归还了池化对象,同时保持原始 socket 不关闭为长连接。所以,我们在程序里一定要确保 EntityUtils 中上述方法被调用。
  • 除了调用 EntityUtils 类, httpclient 也提供了 CloseableHttpResponse 的 close() 方法,我们 debug 来看查看如下:
  • 通过 debug 我们发现 CloseableHttpResponse 的 close() 方法间接调用了 ConnectionHolder 的 releaseConnection() 方法,但是不重用连接。根据以前文章,该方法在不重用连接的情况下除了从 global 池和 individual route 池移除当前池化对象外,还关闭了原始 socket 。所以 response 的 close() 方法消除池化对象,没有长连接,这一点和 EntityUtils 中的方法有所区别。

根据以上分析,在 httpclient 中如果希望重用池化对象并且保持长连接,那么务必调用 EntityUtils 中的方法。如果不希望重用池化对象,不希望有长连接,那么请调用 CloseableHttpResponse 的 close() 方法。

对于使用长连接的情况下也有一些思考:

  • 如果池化对象归还到连接池并且没有关闭原始 socket 保持长连接。
  • 对于服务端可能主动关闭了这个连接,这个时候 httpclient 中的这个连接就为 close_wait 状态,下次申请到的时候是不可用的。
  • 这种情况,调用 http 请求就会失败,在失败的时候连接池会把这个连接关掉,然后利用以前文章里的重试机制重新尝试发送请求,从而解决这种问题。
  • 但是这样做并不优雅,当服务端把大量的连接关闭, httpclient 连接池中就有大量的 close_wait 状态的连接,属于未释放资源。一直到再次有连接申请,发送请求的时候才发现,然后再关闭连接释放资源,重新建立连接。
  • 所以这里推荐以前文章中介绍的启用连接清理方式,这样就避免了 close_wait 状态的未关闭连接。

目前先写到这里,在下一篇文章里我们总结一下 httpclient 连接池的使用建议。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 TA码字 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
HttpComponents HttpClient连接池(10)-使用建议
在以前文章里我们分别介绍了 httpclient 连接池的连接的申请,连接的释放,连接的重用,连接的 keep alive ,连接的可用性检查,空闲连接的清理,请求的 retry ,ssl 请求的支持,长连接的支持等。在这里我们主要总结连接池中的使用建议。
TA码字
2020/04/15
3.1K0
HttpComponents HttpClient连接池(3)-连接的释放
在上一篇文章里我们介绍了 httpclient 连接池中连接的申请,在这里我们主要介绍连接的和释放。
TA码字
2020/04/01
1.5K1
HttpComponents HttpClient连接池(1)-结构
在我们平时进行 http调用的时候经常使用apache httpclient这个组件,它提供了http连接池管理,这里我们对它的实现做分析。另外除了httpclient组件,也可以使用spring的resttemplate组件,resttemplate一般也是整合 httpclient 组件来实现 http 调用。对于比较老的httpclient 版本(3.x)建议不要使用,这里我们基于http components httpclient 4.5.9版本,包括一下内容:
TA码字
2020/04/01
1.6K0
HttpComponents HttpClient连接池(1)-结构
聊聊HttpClient的ResponseHandler
org/apache/http/client/ResponseHandler.java
code4it
2023/10/09
4210
Http 持久连接与 HttpClient 连接池
HTTP协议是无状态的协议,即每一次请求都是互相独立的。因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接。
用户1257393
2018/07/30
2.1K0
Http 持久连接与 HttpClient 连接池
HttpComponents HttpClient连接池(2)-连接的申请
在上一篇文章里我们主要介绍了 httpclient 连接池的关键类和数据结构,在这里我们主要介绍http连接的申请和释放。
TA码字
2020/04/01
1.3K0
高并发场景下的httpClient优化使用
1.背景 我们有个业务,会调用其他部门提供的一个基于http的服务,日调用量在千万级别。使用了httpclient来完成业务。之前因为qps上不去,就看了一下业务代码,并做了一些优化,记录在这里。 先对比前后:优化之前,平均执行时间是250ms;优化之后,平均执行时间是80ms,降低了三分之二的消耗,容器不再动不动就报警线程耗尽了,清爽~ 2.分析 项目的原实现比较粗略,就是每次请求时初始化一个httpclient,生成一个httpPost对象,执行,然后从返回结果取出entity,保存成一个字符串,最后显
老白
2018/03/19
6.8K0
java(优化21) httpClient使用详解
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。
Java架构师必看
2021/06/10
1.1K0
HttpClient4.X 升级 入门 + http连接池使用
http://blog.csdn.net/shootyou/archive/2011/05/12/6415248.aspx
全栈程序员站长
2022/09/15
6410
httpclient4.5如何确保资源释放
更新:releaseConnection()这个方法已经不再推荐了,我用的httpclient4.5的jar包,不需要对request进行这个操作了,看官方文档解释是更换了连接池管理类,最新的是:PoolingHttpClientConnectionManager。
FunTester
2019/08/30
3.2K0
HttpClient详细解释
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。
全栈程序员站长
2022/11/16
1.5K0
HttpComponents HttpClient连接池(7)-重试
在上一篇文章里我们介绍了 httpclient 连接池中空闲连接的清理,在这里我们主要介绍 http 连接的重试机制。
TA码字
2020/04/07
1.9K0
HttpComponents HttpClient连接池(5)-可用性检查
在上一篇文章里我们介绍了 httpclient 连接池中连接的重用,以及连接的 keep alive ,在这里我们主要介绍连接的可用性检查。
TA码字
2020/04/01
1.7K0
HttpComponents HttpClient连接池(6)-连接清理
在上一篇文章里我们介绍了 httpclient 连接池中连接的可用性检查,在这里我们主要介绍空闲 http 连接的清理。对于连接池中的连接基本都是复用的,其中避免不了 server 端主动关闭连接,这个时候取出的连接自然是不可用的,当然可以通过上一篇文章中的可用性检查避免。但同时 httpclient 连接池也提供了 http 连接的清理策略,用来对连接进行清除。
TA码字
2020/04/01
3.3K0
httpClient连接池管理,你用对了?
因为使用它可以有效降低延迟和系统开销。如果不采用连接池,每当我们发起http请求时,都需要重新发起Tcp三次握手建立链接,请求结束时还需要四次挥手释放链接。而链接的建立和释放是有时间和系统开销的。另外每次发起请求时,需要分配一个端口号,请求完毕后在进行回收。
加多
2020/06/12
1.5K0
使用httpclient中EntityUtils类解析entity遇到socket closed错误的原因
本人在使用httpclient做接口测试的时候,最近程序偶然报socket closed错误,上周经过排查发现是request.releaseConnection()这个方法搞得鬼,也是自己学艺不精,没有真正理解方法的含义,改掉之后其他接口就没有出现过这个问题,今天又遇到了,又重新排查了自己的方法,发现还有一种导致socket closed的原因,因为我的响应对象创建时用的是CloseableHttpResponse类,所以需要关闭,在某些时候response太大可能导致使用EntityUtils.toString(entity)解析实体的时候出错,个人理解是由于response的并未完全解析到entity里面时已经执行了close()方法导致的,试着把close()方法后置,完美解决问题。
FunTester
2019/09/10
2.1K0
HttpCanary教程(tcpnodelay设置)
HttpClient优化思路1、池化 2、长连接 3、httpclient和httpget复用 4、合理的配置参数(最大并发请求数,各种超时时间,重试次数)5、异步 6、多读源码
全栈程序员站长
2022/07/31
2K0
HttpClient 在vivo内销浏览器的高并发实践优化
HttpClient作为Java程序员最常用的Http工具,其对Http连接的管理能简化开发,并且提升连接重用效率;在正常情况下,HttpClient能帮助我们高效管理连接,但在一些并发高,报文体较大的情况下,如果再遇到网络波动,如何保证连接被高效利用,有哪些优化空间。
2020labs小助手
2022/08/15
4140
HttpClient使用详解
Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。 第一章 简介 HttpClient是Apache Jakarta Common下的子项目,用来提供高
企鹅号小编
2018/02/20
2.3K1
HttpClient使用详解
HttpClient 基础知识
HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。
Remember_Ray
2020/09/15
6040
相关推荐
HttpComponents HttpClient连接池(10)-使用建议
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档