HttpClient3.1 未releaseConnection导致应用服务器宕机
2012-08-01 16:12
423 查看
报警短信突然一条接一条的出现了,某台服务器宕机了。赶紧ssh到问题服务器,jstack把栈信息导出分析。此时服务器cpu正常,但是resin无响应。初步判断是线程死锁或者线程堵死的问题。
首先我们来分析jstack栈信息。首先应该查找Waiting状态的线程,发现有1000多个线程,我晕。。
分析其中的一个,部分栈信息如下,不过足以说明问题了:
"http--8005-1040$786011311" daemon prio=10 tid=0x00002aab44a25800 nid=0x7d71 in Object.wait() [0x000000004b097000..0x000000004b09ac90]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aaac21d8bc0> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.doGetConnection(MultiThreadedHttpConnectionManager.java:518)
- locked <0x00002aaac21d8bc0> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.getConnectionWithTimeout(MultiThreadedHttpConnectionManager.java:416)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:153)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at com.sohu.twap.service.util.HttpUtil.get(HttpUtil.java:442)
at com.sohu.twap.service.util.HttpUtil.getOriginalContent(HttpUtil.java:462)
at com.sohu.twap.action.AbstractServiceAction.getJsSourceCode(AbstractServiceAction.java:879)
程序在MultiThreadedHttpConnectionManager.doGetConnection方法中的object.wait() 方法中等待了。。。查看代码和google,发现应该是connection连接未释放的问题的。程序的其他地方已经升级到4.0。所以建议大家还是使用最新的4.1版本。参考其官方文档:
wait indefinitely for a connection to free up so that it can be reused.
如果和我们一样使用了MultiThreadedHttpConnectionManager的话,
One main side effect of connection management is that connections must be manually released when no longer used. This is due to the fact that HttpClient cannot
determine when a method is no longer using its connection. This occurs because a method's response body is not read directly by HttpClient, but by the application using HttpClient. When the response is read it must obviously make use of the method's connection.
Thus, a connection cannot be released from a method until the method's response body is read which is after HttpClient finishes executing the method. The application therefore must manually release the connection by calling releaseConnection() on the method
after the response body has been read. To safely ensure connection release HttpClient should be used in the following manner:
Particularly, notice that the connection is released regardless of what the result of executing the method was or whether or not an exception was thrown. For every call to HttpClient.executeMethod there must be a matching
call to method.releaseConnection().
另外一个关于这个问题的email讨论
http://markmail.org/thread/ygejgcnp5kz6f7ox#query:
关于其参数说明:
下面是我们程序的参数:
httpClientManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = httpClientManager .getParams();
params.setStaleCheckingEnabled( true );
params.setMaxTotalConnections(PropConfig.getInstance().getInt( "http.max.total.connections" ,
320));
params.setDefaultMaxConnectionsPerHost(PropConfig.getInstance().getInt( "http.max.connection.perhost" ,
160));
params.setConnectionTimeout(PropConfig.getInstance().getInt( "http.connection.timeout" ,
1000));
params.setSoTimeout(PropConfig.getInstance().getInt( "http.socket.timeout" ,
1000));
httpClient = new HttpClient(httpClientManager );
默认MaxConnectionsPerHost是2,对于SOA应用的话,这样就限制的对一台服务器调用只用两个并发,注意一定要更改,其实httpclient发表于2003年,作者没有意识到现在SOA架构的广泛使用,况且httpclient原来的目的是实现浏览器的连接部分,设置默认值为2也是理所当然的。
关于超时和maxconenectionperhost的讨论:
http://www.scriptkiddie.org/blog/2010/09/06/why-i-hate-java-httpclient-maxconnectionsperhost/
首先我们来分析jstack栈信息。首先应该查找Waiting状态的线程,发现有1000多个线程,我晕。。
分析其中的一个,部分栈信息如下,不过足以说明问题了:
"http--8005-1040$786011311" daemon prio=10 tid=0x00002aab44a25800 nid=0x7d71 in Object.wait() [0x000000004b097000..0x000000004b09ac90]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aaac21d8bc0> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.doGetConnection(MultiThreadedHttpConnectionManager.java:518)
- locked <0x00002aaac21d8bc0> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$ConnectionPool)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.getConnectionWithTimeout(MultiThreadedHttpConnectionManager.java:416)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:153)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at com.sohu.twap.service.util.HttpUtil.get(HttpUtil.java:442)
at com.sohu.twap.service.util.HttpUtil.getOriginalContent(HttpUtil.java:462)
at com.sohu.twap.action.AbstractServiceAction.getJsSourceCode(AbstractServiceAction.java:879)
程序在MultiThreadedHttpConnectionManager.doGetConnection方法中的object.wait() 方法中等待了。。。查看代码和google,发现应该是connection连接未释放的问题的。程序的其他地方已经升级到4.0。所以建议大家还是使用最新的4.1版本。参考其官方文档:
Release the Connection
This is a crucial step to keep things flowing. We must tell HttpClient that we are done with the connection and that it can now be reused. Without doing this HttpClient willwait indefinitely for a connection to free up so that it can be reused.
method.releaseConnection();
如果和我们一样使用了MultiThreadedHttpConnectionManager的话,
One main side effect of connection management is that connections must be manually released when no longer used. This is due to the fact that HttpClient cannot
determine when a method is no longer using its connection. This occurs because a method's response body is not read directly by HttpClient, but by the application using HttpClient. When the response is read it must obviously make use of the method's connection.
Thus, a connection cannot be released from a method until the method's response body is read which is after HttpClient finishes executing the method. The application therefore must manually release the connection by calling releaseConnection() on the method
after the response body has been read. To safely ensure connection release HttpClient should be used in the following manner:
MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); HttpClient client = new HttpClient(connectionManager); ... // and then from inside some thread executing a method GetMethod get = new GetMethod("http://httpcomponents.apache.org/"); try { client.executeMethod(get); // print response to stdout System.out.println(get.getResponseBodyAsStream()); } finally { // be sure the connection is released back to the connection // manager get.releaseConnection(); }
Particularly, notice that the connection is released regardless of what the result of executing the method was or whether or not an exception was thrown. For every call to HttpClient.executeMethod there must be a matching
call to method.releaseConnection().
另外一个关于这个问题的email讨论
http://markmail.org/thread/ygejgcnp5kz6f7ox#query:
关于其参数说明:
maxConnectionsPerHost | The maximum number of connections that will be created for any particular HostConfiguration. Defaults to 2. |
maxTotalConnections | The maximum number of active connections. Defaults to 20. |
httpClientManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = httpClientManager .getParams();
params.setStaleCheckingEnabled( true );
params.setMaxTotalConnections(PropConfig.getInstance().getInt( "http.max.total.connections" ,
320));
params.setDefaultMaxConnectionsPerHost(PropConfig.getInstance().getInt( "http.max.connection.perhost" ,
160));
params.setConnectionTimeout(PropConfig.getInstance().getInt( "http.connection.timeout" ,
1000));
params.setSoTimeout(PropConfig.getInstance().getInt( "http.socket.timeout" ,
1000));
httpClient = new HttpClient(httpClientManager );
默认MaxConnectionsPerHost是2,对于SOA应用的话,这样就限制的对一台服务器调用只用两个并发,注意一定要更改,其实httpclient发表于2003年,作者没有意识到现在SOA架构的广泛使用,况且httpclient原来的目的是实现浏览器的连接部分,设置默认值为2也是理所当然的。
关于超时和maxconenectionperhost的讨论:
http://www.scriptkiddie.org/blog/2010/09/06/why-i-hate-java-httpclient-maxconnectionsperhost/
相关文章推荐
- HttpClient3.1 未releaseConnection导致应用服务器宕机
- 那些年我们踩到过的坑(二):3.1 版 MultiThreadedHttpConnectionManager 未releaseConnection导致应用服务器宕机
- 谈HttpClient(3.1版本)与HttpURLConnection
- HttpClient release connection 该放手的时候必须放手
- HttpUrlConnection与HttpClient的认识(六) -实际应用之刷网络流量
- HttpClient和HttpURLConnection获取服务器返回的内容
- 安卓应用的HTTP请求方式:Apache HTTP Client和HttpURLConnection
- How to release the port of TCP Client immediately when the connection is disconnect with the TCP server. - TCP 客户端与 TCP 服务器断开连接后
- Android使用HttpURLConnection和HttpClient请求服务器数据
- android中HttpClient和HttpConnection的区别和应用
- 客户端和应用服务器之间利用HttpClient和Servlet交互JSON对象进行通信
- 解决:HttpClient导致应用出现过多Close_Wait的问题
- Android网络编程之URLConnection和HttpClient访问服务器
- 由于httpClient调用导致的ESTABLISHED过多和 Connection rest by peer 异常
- android中HttpClient和HttpConnection的区别和应用
- android HttpURLConnection 与服务器通信(包含对struts2的使用)
- Win2003 WinHTTP Web Proxy Auto-Discovery Service 导致的服务器重启
- android 网络通信之HttpURLConnection与HttpClient
- Android网络(3):HttpClient作客户端,Tomcat Servlet作服务器的交互示例
- Android---SmartImageView和AsyncHttpClient的应用之《新闻客户端》案例