java httpclient 关闭_【Java系列007】HttpClient调用:你考虑过关闭连接、并发了吗?...

你好!我是miniluo,今天和你分享使用HttpClient过程中,未考虑释放连接和并发导致的坑。

HttpClient在项目中还是比较常见的,主要都是通过GET或POST请求第三方以获取响应结果。前段时间还了解到也有企业用它来做爬虫。下面我们就从两方面来一起学习HttpClient。

强占着不放

我们先来看一张因未释放连接导致的异常图。

d9907b38aa3952d91310d3c1734652af.png

我们再来看代码,代码很简单,用一个static修饰HttpClient的一个对象,也是用static的方式实例化(并发下,static实例化的对象是线程不安全的)。

1@Slf4j

2public class MyHttpClientTest{

3    private static HttpClient client;

4    static {

5        RequestConfig requestConfig = RequestConfig.custom()

6                .setConnectTimeout(5000)

7                .setConnectionRequestTimeout(3000)

8                .setSocketTimeout(5000).build();

9        client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)

10                .build();

11    }

12

13    @Test

14    public void testHttpClient(){

15        for (int i = 0; i 

16            String url = "http://127.0.0.1:9092/learn/product/get/12";

17            HttpGet httpGet = new HttpGet(url);

18            try {

19                HttpResponse res = client.execute(httpGet);

20            } catch (IOException e) {

21                log.error("异常: ",e);

22                return;

23            }

24        }

25    }

26}

我们看回异常图,图中有2个红框,我们先来看第一个红框的“[total kept alive: 0; route allocated: 2 of2; total allocated: 2 of 20]”,这个DEBUG级别日志描述的什么意思呢?也就是说这个route下共有2个连接,已用2个;pool共有20个,已用2个。再来看第二个红框“Timeout waiting for connection from pool”,从连接池获取连接等待超时。奇怪吧,这顺序执行也会出现?这其实是前两个连接响应结果回来后,并没有释放连接资源,导致后面的请求等待超时。

我们看看PoolingHttpClientConnectionManager类的构造函数,其给Pool初始化时给maxConnPerRoute和maxConnTotal设置了默认值。

1    public PoolingHttpClientConnectionManager(

2        final HttpClientConnectionOperator httpClientConnectionOperator,

3        final HttpConnectionFactory connFactory,

4        final long timeToLive, final TimeUnit tunit){

5        super();

6        this.configData = new ConfigData();

7        //defaultMaxPerRoute默认为2,maxTotal默认为20

8        this.pool = new CPool(new InternalConnectionFactory(

9                this.configData, connFactory), 2, 20, timeToLive, tunit);

10        this.pool.setValidateAfterInactivity(2000);

11        this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator");

12        this.isShutDown = new AtomicBoolean(false);

13    }

所以当请求连接被占用2个后,后面的请求并不会获取到连接,这么说,我们需要释放连接资源。这里我们需要介绍EntityUtils这个类,里面包含了两个释放连接资源的方法consumeQuietly(HttpEntity entity)和consume(HttpEntity entity),前者内部也是请求后者完成关闭InputStream。调整后的代码如下:

1@Test

2    public void testHttpClient(){

3        for (int i = 0; i 

4            String url = "http://127.0.0.1:9092/learn/product/get/12";

5            HttpGet httpGet = new HttpGet(url);

6            HttpResponse res = null;

7            try {

8                res = client.execute(httpGet);

9            } catch (IOException e) {

10                log.error("异常: ", e);

11                return;

12            } finally {

13                if (null != res) {

14                    EntityUtils.consumeQuietly(res.getEntity());

15                }

16            }

17        }

18    }

调整完代码后,我们执行后发现5个请求都能正确请求并得到响应结果。或许有同学会问到如果我调整maxConnPerRoute和maxConnTotal不也行吗?可以,但是你的连接还是没有释放,当超过你设置值后也会出现无法获得连接池的问题。

被CloseableHttpClient名字所坑

最近项目中就是使用到CloseableHttpClient实现请求第三方,踩完上面的坑后,我们在项目中写了一个工厂类内部用枚举方式实现单例。经过并发测试后,的确没有出现上述坑,看了CloseableHttpClient有一个execute方法,最后也有释放资源,所以没有在意。直到今天写文章对应的测试案例我才发现我被这个方法欺骗了。

CloseableHttpClient的execute()重载了多个方法,而实际调用能释放资源的execute必须是包含ResponseHandler extends T>这个属性,否则和原有HttpClient方式是一样的。为何,模拟高并发下并没有发生问题呢?这是因为项目中请求响应结果后是用下面的代码完成数据获取的。

1 HttpResponse response = client.execute(get);

2 String res = EntityUtils.toString(response.getEntity());

跟进EntityUtils.toString()方法的最底层调用,会执行InputStream关闭流,和上文说的consume方法一样。但是这里坑就坑在,如果请求第三方超时或其他异常,则直接跳过,并没有执行上面的toString()方法,那就不会释放连接资源。

知道坑所在,要解决也就好办。可以有下述两个方案:

1、外层调用增加finally释放连接,上文所述。

2、实例化一个ResponseHandler对象,调用实现了释放连接资源的方法。

总结

今天我们一起学习了HttpClient和CloseableHttpClient没有正确释放连接,以及并发受限的问题。实际项目中如果没有考虑到这两个情况,则会带来生产问题,后面的请求一直无法获取到连接资源,以及并发量起不来。很多项目并不会有这个问题是因为HttpClient和CloseableHttpClient并不是单例的,每次使用都会是新的实例。希望通过今天的学习对你日后使用HttpClient更加得心应手。由于篇幅问题,没有把CloseableHttpClient案例放上来,有兴趣的同学可以到GitHub上下载(https://github.com/littleluo/bj-share-java.git)。

思考和讨论

1、案例中,我们使用了static和枚举的方式解决单例问题,除了这两种方法外,还有哪些方式呢?他们各自的优缺点是什么?

2、说回前面关于分布式锁的文章中,我们用到了redis,也提到client.close()方式归还连接,为何是归还连接,而不是关闭连接呢?

欢迎留言与我分享和指正!也欢迎你把这篇文章分享给你的朋友或同事,一起交流。

感谢您的阅读,我们下节再见!

扫码关注我们,与君共进

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/431852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

统计学中【矩】的概念

这个问题要从物理学、统计学和语源学三个角度来回答。矩,英文为moment。历史上出现的顺序是物理moment -> 统计moment -> 数学moment,并且数学moment完全是对此的归纳,并不是起源。先整理一下历史:力矩这个概念最早是由阿基…

linux 内核长延时方法

忙等待 如果你想延时执行多个时钟嘀哒, 允许在值中某些疏忽, 最容易的( 尽管不推荐 ) 的实 现是一个监视 jiffy 计数器的循环. 这种忙等待实现常常看来象下面的代码, 这里 j1 是 jiffies 的在延时超时的值: while (time_before(jiffies, j1)) cpu_relax(); 对 cpu_relex 的调用…

郑州it java_郑州Java网站开发

详细信息:阶段:Java语言基础:Java开发环境配置、编程基础、算法基础、常用数据结构、企业编程规范。Java面向对象:理解java面向对象的思想,掌握面向对象特性:封装、继承、多态等,面向对象程序设…

UESTC_秋实大哥下棋 2015 UESTC Training for Data StructuresProblem I

I - 秋实大哥下棋 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Status胜负胸中料已明,又从堂上出奇兵。秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的…

java数据类型及表示范围_Java数据类型及对应取值范围

在Java中,数据类型分为两大种:基本数据类型(值类型)和包装类型(引用数据类型)。基本数据类型不是对象,不能调用toString()、hashCode()、getClass()、equals()等方法。8种基本数据类型-----8种包装类型整型:byte  Byte     …

java开发cgi_編寫CGI小結(Java)

轉載請注明出處:http://blog.csdn.net/hungryhuang/article/details/6601684。由於Carl要用到我的程序,我們便合作工作。但是他寫的程序是Python的,我寫的程序是Java的,必須得找一種方式進行通信。盡管有Jython這些東西&#xff0…

腾讯后台开发面试总结,原创,吐血推荐!!

前段时间专心面过腾讯,经过了N轮的技术面,结果还是挂了,但没挂在技术面,比较欣慰,回来之后写一点总结,以供有梦想进入腾讯做后台服务器开发的同学参考,本文章为胡成精心总结,胡成原创…

java 6大原则_java 6大设计原则 一:观察者模式

解耦常用的模式OrderService.javaServicepublic class OrderService{AutowiredApplicationContext applicationContext ;public void saveOrder(){//1.创建订单System.out.println(“1.创建订单”);OrderEvent event new OrderEvent("参数")application…

jbb是什么梗_子水是什么意思,子水命理

子水是十二地支之一,那么命中有子水的代表的是什么呢?适合什么方位呢?有什么喜忌吗?怎么分析你呢?现在金宝贝起名网为你介绍子水是什么意思,子水命理的相关文章。子水是什么意思,子水命理八字地支:子水是什么意思1、对…

java语言实现一个长度为n_Java语言实现求解一元n次多项式的方法示例[Java代码]...

本文主要向大家介绍了Java语言实现求解一元n次多项式的方法示例,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。项目需要做趋势预测,采用线性拟合、2阶曲线拟合和指数拟合的算法,各种线性拟合算法写成矩阵大概是这么…

java rmi 是否 必要_Java学习之路-RMI学习

Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的…

c++将文本中的字符串一次读入到内存

这段代码是将文本文件中的全部字符读入到内存中&#xff0c;这样的速度是很快的 char buf[1024*800];int MAXS 10000000;freopen("d:\\4.txt", "rb", stdin);int len fread(buf, 1, 100000, stdin);buf[len] \0;cout << buf[10]; 转载于:https://…

JAVA写同步栈_tomcat实现的同步队列和同步栈

tomcat实现的同步队列&#xff0c;同步栈用于数据量比较固定且基本很少删除的场景&#xff0c;尽可能减少内存消耗。同步队列/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with…

IOS高级编程之二:IOS的数据存储与IO

一、应用程序沙盒 IOS应用程序职能在系统为该应用所分配的文件区域下读写文件&#xff0c;这个文件区域就是应用程序沙盒。所有的非代码文件如&#xff1a;图片、声音、映象等等都存放在此。 在mac中command&#xff0b;shift&#xff0b;G命令&#xff0c;然后输入users/用户名…

安卓投屏大师_苹果,安卓手机如何免费投屏?只要悄悄按下这里,便能轻松实现...

现在很多手机都有自带投屏功能&#xff0c;这样一来我们便可以将所看的视频&#xff0c;所玩的游戏投屏到电脑或电视上了&#xff0c;当然也需要这些设备支持投屏才行。一、无线投屏1、苹果手机苹果手机的投屏功能在哪里呢&#xff1f;只要打开苹果手机从下往上滑动&#xff0c…

java 反射解析xml_java反射获取xml元素

类名:class Person {public void run(String who){System.out.println("Person::run()" who);}public void jump(String who){System.out.println("Person::jump()" who);}public void run(){System.out.println("Person::run()");}public voi…

怎样的中奖算法能让人信服

话说写一个抽奖程序还不容易&#xff0c;不就是生成一个随机数吗&#xff0c;哪需什么算法之类的。 从技术上说&#xff0c;这确实不难。事实上&#xff0c;你怎么写都可以&#xff0c;因为程序只运行在特定的设备上&#xff0c;外人根本无法了解其中的细节。 那么问题就来了&a…

b站电脑客户端_如何将B站的flv格式的视频转换成mp4格式

经常看到B站有精彩的视频片段&#xff0c;于是想把这些视频下载保存到电脑&#xff0c;但是发现没有下载按钮&#xff0c;是不是很悲催。有些时候想从优酷、土豆网这些视频网站下载视频&#xff0c;结果却提示要先下载视频客户端才能继续下载视频&#xff0c;运气差的话&#x…

linux Packet socket (1)简单介绍

本文主要来自于linux自带的man packet手冊&#xff1a; http://man7.org/linux/man-pages/man7/packet.7.html 平时常常使用的INET套接字提供的是7层的抓包能力&#xff0c;抓上来的data直接就是tcp或者udp的payload&#xff0c;无需关心L3和L4的头部信息。 Packet套接字提供的…

asp.net 设置 excel alignment_教你如何用Python轻轻松松操作Excel、Word、CSV,一文就够了,赶紧码住!!!...

作者&#xff1a;奈何缘浅wyjhttps://juejin.im/post/6868073137263607821Python 操作 Excel常用工具数据处理是 Python 的一大应用场景&#xff0c;而 Excel 又是当前最流行的数据处理软件。因此用 Python 进行数据处理时&#xff0c;很容易会和 Excel 打起交道。得益于前人的…