文档章节

HttpClient 与 Close_Wait

银月光海
 银月光海
发布于 2016/01/26 13:25
字数 1125
阅读 71
收藏 1

服务器A需要通过HttpClient去连接另一个系统B提供的服务,运行一段时间后抛出以下异 常:java.net.SocketException: Connection reset by peer: socket write error close_wait

在服务器B上运行netstat命令,发现大量连接处于CLOSE_WAIT 状态。

问题分析:

简单来说CLOSE_WAIT数目过大是由于被动关闭连接处理不当导致的。

我说一个场景,服务器A会去请求服务器B上面的apache获取文件资源,正常情况下,如果请求成功,那么在抓取完资源后服务器A会主动发出关闭连 接的请求,这个时候就是主动关闭连接,连接状态我们可以看到是TIME_WAIT。如果一旦发生异常呢?假设请求的资源服务器B上并不存在,那么这个时候 就会由服务器B发出关闭连接的请求,服务器A就是被动的关闭了连接,如果服务器A被动关闭连接之后自己并没有释放连接,那就会造成CLOSE_WAIT的 状态了。

所以很明显,问题还是处在程序里头。

原始代码块:


  
  
  1. try 
  2. client = HttpConnectionManager.getHttpClient(); 
  3. HttpGet get = new HttpGet(); 
  4. get.setURI(new URI(urlPath)); 
  5. HttpResponse response = client.execute(get); 
  6. if (response.getStatusLine ().getStatusCode () != 200) { 
  7. return null; 
  8. HttpEntity entity =response.getEntity(); 
  9.  
  10. if( entity != null ){ 
  11. in = entity.getContent(); 
  12. ..... 
  13. return sb.toString (); 
  14.  
  15. catch (Exception e) 
  16. e.printStackTrace (); 
  17. return null; 
  18. finally 
  19. if (isr != null){ 
  20. try 
  21. isr.close (); 
  22. catch (IOException e) 
  23. e.printStackTrace (); 
  24. if (in != null){ 
  25. try 
  26. <span style="color:#ff0000;">in.close ();</span> 
  27. catch (IOException e) 
  28. e.printStackTrace (); 

HttpClient使用我们常用的InputStream.close()来确认连接关闭,分析上面的代码,一旦出现非200的连接,这个连接将永远僵死在连接池里头,因为inputStream得不到初始化,永远不会调用close()方法了。

通过代码稍微修改,更严谨的处理异常情况就可以解决问题了:


  
  
  1. public static String readNet (String urlPath) 
  2. StringBuffer sb = new StringBuffer (); 
  3. HttpClient client = null
  4. InputStream in = null
  5. InputStreamReader isr = null
  6. HttpGet get = new HttpGet(); 
  7. try 
  8. client = HttpConnectionManager.getHttpClient(); 
  9. get.setURI(new URI(urlPath)); 
  10. HttpResponse response = client.execute(get); 
  11. if (response.getStatusLine ().getStatusCode () != 200) { 
  12. get.abort(); 
  13. return null; 
  14. HttpEntity entity =response.getEntity(); 
  15.  
  16. if( entity != null ){ 
  17. in = entity.getContent(); 
  18. ...... 
  19. return sb.toString (); 
  20.  
  21. catch (Exception e) 
  22. get.abort(); 
  23. e.printStackTrace (); 
  24. return null; 
  25. finally 
  26. if (isr != null){ 
  27. try 
  28. isr.close (); 
  29. catch (IOException e) 
  30. e.printStackTrace (); 
  31. if (in != null){ 
  32. try 
  33. in.close (); 
  34. catch (IOException e) 
  35. e.printStackTrace (); 

显示调用HttpGet的abort,这样就会直接中止这次连接,我们在遇到异常的时候应该显示调用,因为谁能保证异常是在InputStream in赋值之后才抛出的呢。

more:

首先我们知道,如果我们的服务器程序处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!

因为如果是CLIENT端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet:

Client –-> FIN  –-> Server
Client <–- ACK  <–- Server
这时候Client端处于FIN_WAIT_2状态;而Server 程序处于CLOSE_WAIT状态。
Client <–- FIN  <–- Server
这时Server 发送FIN给Client,Server 就置为LAST_ACK状态。
Client –-> ACK  –-> Server
Client回应了ACK,那么Server 的套接字才会真正置为CLOSED状态。

Server 程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Client,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。

通常来说,一个CLOSE_WAIT会维持至少2个小时的时间(这个时间外网服务器通常会做调整,要不然太危险了)。如果有个流氓特地写了个程序,给你造成一堆的CLOSE_WAIT,消耗

你的资源,那么通常是等不到释放那一刻,系统就已经解决崩溃了。

只能通过修改一下TCP/IP的参数,来缩短这个时间:修改tcp_keepalive_*系列参数有助于解决这个问题。

但是实际上,还是主要是因为我们的程序代码有问题,

more:

最近做httpclient做转发服务,发现服务器上总是有很多close_wait状态的连接,而且这些连接都不会关闭,最后导致服务器没法建立新的网络连接,从而停止响应。

后来在网上搜索了一下,发现解决的方法也很简单,如果想重用连接,那就使用连接管理器,从连接管理器里获取连接,然后定时的用连接管理器来释放空闲连接。httpclient自带了SimpleHttpConnectionManager,提供了

Java代码 


  
  
  1. closeIdleConnections(long idleTimeout)  

这样的方法。

如果不需要重用链接,则直接在httpmethod创建时,设置一个http头信息就可以了

Java代码


  
  
  1. httpmethod.setRequestHeader("Connection", "close");   

这样就不会有恼人的close_wait了。

本文转载自:http://network.51cto.com/art/201406/442097.htm

共有 人打赏支持
银月光海

银月光海

粉丝 34
博文 365
码字总数 46223
作品 0
浦东
项目经理
Httpclient4.4之原理(HttpClient接口)

HttpClient接口对于HTTP请求执行是关键。它对请求执行处理没有限制,而且舍弃连接管理,状态管理,认证和重定向到个人实现的那些方面的详细细节。这让使用附加功能修饰接口更容易了,例如res...

柳哥
2015/05/22
0
4
聊聊spring cloud gateway的NettyConfiguration

序 本文主要研究下spring cloud gateway的NettyConfiguration NettyConfiguration spring cloud gateway使用的是reactor的httpclient,其通过nettyClientOptions这个bean来进行构造options,......

go4it
06/03
0
0
.NET Core 2.1中的HttpClientFactory最佳实践

ASP.NET Core 2.1中出现一个新的HttpClientFactory功能, 它有助于解决开发人员在使用HttpClient实例从其应用程序发出外部Web请求时可能遇到的一些常见问题。 介绍 在.NETCore平台的2.1新增了...

dotNET跨平台
08/16
0
0
.NetCore 2.1中的HttpClientFactory最佳实践

.NET Core 2.1中的HttpClientFactory最佳实践 ASP.NET Core 2.1中出现一个新的HttpClientFactory功能, 它有助于解决开发人员在使用HttpClient实例从其应用程序发出外部Web请求时可能遇到的一...

Chaunce
08/14
0
0
Servlet HttpClient 转发 SocketClose Exception

系统部署要求,APP要部在内网,外网必须通过一次Web代理转发进来.就用Servlet + HttpClient 代理; 在内网测试的时挺正常的;上生产经常发现下载8M以上的文件就会出现Socket Colse Exception; 跟...

vidy_tu
2014/12/07
0
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Memcached启动参数详解

memcached -d -m 1024 -l 192.168.100.101 -p 11211 -P /tmp/memcached.pid -c 1024 -f 1.25 -n 80 -t 16 运行参数描述 -d:以守护(daemon)进程方式启动; -u:是运行Memcache的用户,例如 ......

月下狼
23分钟前
0
0
xgboost-kaggle

https://www.kaggle.com/dansbecker/xgboost This tutorial is part of the Learn Machine Learning series. In this step, you will learn how to build and optimize models with the powe......

tantexian
24分钟前
0
0
nginx学习八 代理服务

最常用的语法 proxy_pass Syntax: proxy_pass URL;Default: --Context:location.if in location,limit_exception 反向代理 例:/etc/nginx/conf.d/default.conf 反向代理(代理服务端)......

Romanceling
31分钟前
0
0
npm ERR! Unexpected end of JSON ...

npm install 报错: npm ERR! Unexpected end of JSON input while parsing near '..."^2.8.14"},"_hasShrin' npm ERR! A complete log of this run can be found in: ... 打开终端 命令: 第......

大_侠
35分钟前
0
0
Android中的设计模式之责任链模式

参考 《设计模式:可复用面向对象软件的基础 》5.1 Chain of responsibility 职责链 对象行为型模式 《Android源码设计模式解析与实战》第9章 使编程更有灵活性--责任链模式 意图 使多个对象...

newtrek
38分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部