HttpClient 如何正确的释放资源

HttpClient 需要关闭的资源

使用HttpClient 访问会涉及到三个层次的资源, 从上往下依次是:

  1. HttpClient 类型的对象。这是Http 呼叫的客户端。
  2. Http的请求的对象,一般是HttpGet 或者HttpPost, 这个代码了一个Http的链接请求。
  3. 从目标地址获取的响应流 HttpResponse,某些状况下响应的结果是以流的形式返回,使用完成最好是关闭流。

HttpClient 资源关闭的方式

资源的初始化的顺序是 HttpClient > Http请求 > 响应流, 在释放时以从下往上的顺序释放, 依次是: 关闭响应流 > 关闭Http请求 > 关闭HttpClient 。
这三种类型的资源释放的方式分别是:

  1. HttpClient 使用 close() 方法
  2. Http请求 使用 close() 方法
  3. 响应流可以使用Stream 的close() 方法关闭, HttpClient 也提供了EntityUtils.consume()方法用来关闭响应流。

Java 处理资源释放的语法

  1. 在早期的Java 语法中, 主要在 try finally 语法中释放资源
  2. 在Java 8 之后, 使用 try 资源之后就可以直接释放资源。

HttpClient 资源释放示例代码

综合以上, 在 HttpClient 中释放资源就可以多种方式。

1. [推荐] 使用 try 资源 + EntityUtils.consume()

在Java 8 及以上的版本, 推荐使用try 资源 释放资源, 理由是简洁。
对响应流的释放使用EntityUtils.consume(entity);
完整的示例代码如下:

	@Test
	public void byTryRelease() throws Exception {
		try (CloseableHttpClient httpclient = HttpClients.createDefault()) { //3. 关闭客户端资源
		    HttpGet httpGet = new HttpGet("http://www.baidu.com");
		    try (CloseableHttpResponse response = httpclient.execute(httpGet)) { //2. 关闭响应资源    	
		        HttpEntity entity = response.getEntity();			     
		        EntityUtils.consume(entity); //1. 关闭响应流
		    }	  
		}
	}
2. 使用 try finally + EntityUtils.consume()
  • 使用try finally 释放资源
  • 使用 EntityUtils.consume() 释放资源
	@Test
	public void byManualRelease() throws Exception{
		CloseableHttpClient httpclient = HttpClients.createDefault();
		try {		
			HttpGet httpGet = new HttpGet("http://www.baidu.com");
			CloseableHttpResponse response = httpclient.execute(httpGet);
			try {
				 HttpEntity entity = response.getEntity();		
				 EntityUtils.consume(entity); //1. 关闭响应流
			}finally {
				response.close(); //2. 关闭响应资源    	
			}
		}finally {
			httpclient.close();//3. 关闭客户端资源
		}      	          
	}
3. 使用 try finally + 手动关闭输入流
  • 使用try finally 释放资源
  • 通过Stream 的close() 关闭输入流
	@Test
	public void byManualRelease2() throws Exception{
		CloseableHttpClient httpclient = HttpClients.createDefault();
		try {		
			HttpGet httpGet = new HttpGet("http://www.baidu.com");
			CloseableHttpResponse response = httpclient.execute(httpGet);
			try {
				 HttpEntity entity = response.getEntity();		
				 //EntityUtils.consume(entity); //1. 关闭响应流
				 if (entity != null) {
	                    InputStream inStream = entity.getContent();
	                    try {
	                        inStream.read();
	                    }  finally {
	                        inStream.close();   //1. 关闭响应流
	                    }
	                }
			}finally {
				response.close(); //2. 关闭响应资源    	
			}
		}finally {
			httpclient.close();//3. 关闭客户端资源
		}      	          
	}

总结

  • 以上三种方式的实现的效果是一样的, 差别是代码的简洁性和美观性
  • Java 8 推荐使用 try 资源的方式使用和释放资源。


HttpClient close_wait不释放是指当HttpClient执行完请求后,关闭连接后却不能及时释放连接,出现了close_wait状态,可能会导致资源的浪费和程序性能的降低。这种情况通常发现在服务器的TCP连接数一直在增加,却一直处于close_wait状态,并且ClientSocketImpl的状态一直是CLOSED_WAIT,造成资源的浪费和服务器处理能力的下降。 造成HttpClient close_wait不释放的原因可能有以下几点: 1. 连接池没有及时释放连接。HttpClient有一个默认的连接池管理器,如果连接池同时被多个线程调用,可能会出现连接池没有及时释放连接的情况,导致close_wait状态的产生。 2. Http客户端没有及时关闭连接。有些Http客户端请求完成后不主动释放连接,导致连接一直处于close_wait状态。 3. 服务器没有及时关闭连接。如果服务器没有在超时时间内关闭连接,那么连接就会一直处于close_wait状态。 解决HttpClient close_wait不释放的方法有以下几点: 1. 使用HttpClient连接池管理器时,需要设置合理的连接超时时间和请求超时时间,及时关闭闲置连接或者过期的连接。 2. 在Http客户端请求完成后,及时关闭连接,避免连接一直处于close_wait状态。 3. 调整服务器的超时时间,及时关闭连接。 4. 调整服务器的TCP/IP协议参数,设置合理的TIME_WAIT时间。 总之,为了避免出现close_wait状态的连接,需要在使用HttpClient连接池管理器时,合理调整连接超时时间和请求超时时间,并在请求完成后及时释放连接,避免资源的浪费和程序性能的降低。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oscar999

送以玫瑰,手留余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值