异常信息:
org.apache.http.conn.HttpHostConnectException: Connection to http://xxx.xxxx.com refused
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:190)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:645)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.hcit.SendNoYdMobile.run(SendNoYdMobile.java:91)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
Caused by: java.net.ConnectException: Connection timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:529)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:127)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
... 9 more
高峰期时通常报这样的错:
2013-03-01 16:34:50[ INFO] org.apache.http.impl.client.DefaultHttpClient -->I/O exception (java.net.SocketException) caught when processing request: Connection reset
2013-03-01 16:34:50[ INFO] org.apache.http.impl.client.DefaultHttpClient -->Retrying request
引自:http://blog.sina.com.cn/s/blog_3cdcd4a90100j0xf.html
【一个故障引发的话题】
最近,项目中的短信模块收到一个故障日志,要求我协助调查一下:
2010-05-07 09:22:07,221 [?:?] INFO httpclient.HttpMethodDirector - Retrying request
:org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(Unknown Source)
2010-05-07 09:22:07,223 [?:?] INFO httpclient.HttpMethodDirector - I/O exception (org.apache.commons.httpclient.NoHttpResponseException) caught when processing request: The server sms failed to respond
:org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(Unknown Source)
查阅了HttpClient官方的异常说明文档(http://hc.apache.org/httpclient-3.x/exception-handling.html),可以看到以下一段话:
In some circumstances, usually when under heavy load, the web server may be able to receive requests but unable to process them. A lack of sufficient resources like worker threads is a good example. This may cause the server to drop the connection to the client without giving any response. HttpClient throws NoHttpResponseException when it encounters such a condition. In most cases it is safe to retry a method that failed with NoHttpResponseException.
在某些情况下,通常在重负载下时,Web服务器可能能够接收请求,但无法处理它们。缺乏足够的资源,比如工作线程,这可能会导致服务器断开连接的客户端没有给予任何回应。当它遇到这样的条件HttpClient会抛出NoHttpResponseException。此异常是由于服务器端过载而拒绝接受请求(不再响应)所致。
老外有一篇文章,很好的描述了类似代码的性能隐患:《HttpClient容易忽视的细节——连接关闭》
1、英文原文:http://www.codeweblog.com/httpclient-s-easy-to-overlook-the-details-the-connection-is-closed/
2,中文翻译:http://www.iteye.com/topic/234759
总述:实现一个HTTP接口不是件困难的事情,但是如何让这样的HTTP接口在高压力下(短时间内大数据量)也有稳定良好的表现,则不仅仅是HTTP服务器端需要做好设计与优化,而且HTTP客户端方面也同样需要非常谨慎与注意一些代码细节。否则,很有可能因(双方或单方)代码或配置中存在性能隐患,在软硬件环境的配合下就会出现一些“灵异”故障。
【HTTP协议知识
为便于读者理解后文,先简述一些与HTTP性能密切相关的、又常常被工程师们所不深究的HTTP协议基础知识。
一,什么是HTTP KeepAliv 电子邮件
HTTP KeepAlive是就是通常所称的长连接。KeepAlive即服务器端为同一客户端保持连接一段时间(不立即关闭),以便于更多来自于此客户端的后续请求不断的利用此连接直至连接超时。
在HTTP1.0和HTTP1.1协议中都有对的KeepAlive的支持。其中HTTP1.0需要在请求头中增加“连接:保持活动”才能够支持,而HTTP1.1默认支持。
该属性的更多阐述:
1,下一个请求是在完成之前请求的响应被客户端接收的情况下才发出。因此需要在向客户端写完之前的请求的响应后才能触发。
2、HTTP协议是基于TCP协议的,故服务器端与客户端都有可能关闭连接。KeepAlive只是表明了服务器端面对连接的一种优化策略,而客户端也完全可以主动关闭之(不利用)。
二,KEEPALIVE的好处与坏处
KeepAlive带来的好处是可以减少HTTP连接的开销,提高性能。比如,同一页面中如有很多内嵌的图片、JS、CSS等请求,则可以利用此特新性,使用少量的连接数(IE下一般是2个)更快的下载下来,使得网页更快的展示出来。
QeepAlive的坏处是:
如果有大量不同的客户端同时(或瞬间)请求服务器端,且每一个客户端的都长期占用连接(比如:不关闭且ConnectionTimeOut设置过长)或服务器端也不快速失效连接(KeepAliveTimeout参数设置过大)的话,可能会快速占满服务器连接资源,导致更多的请求被排队或被拒绝或服务器down掉。
总结:浏览器作为一种HTTP客户端,充分的、很好的利用了HTTP协议的KeepAlive,让我们的浏览更加快速;而我们自写的HTTP客户端程序在KeepAlive特性(服务器已开启)下,需要以高数据量访问一个HTTP接口的时候,每一次请求应当尽快关闭连接释放资源(重点推荐)或者在同一连接上适当多发几次请求(不推荐)。
【高性能HTTP应用的策略】
所以,当我们需要一个高性能的HTTP接口型应用时:
1,服务器端:关闭KeepAlive功能。
2、服务器端:最好直接支持HTTP协议(注意用POST,不要GET),而不是任何包装过的协议,比如:hessian/soap等。
3、服务器端:在一个请求中,最好设计成:支持多条指令批处理,以节省连接数。
4、服务器端:对请求的处理应当尽可能的快(如在150ms内)。
5、客户端:在代码中,同一个客户端实例中全部请求结束后应主动关闭连接(无须事先设置客户端的ConnectionTimeOut参数)。
6、客户端:如服务器未关闭KeepAlive,在同一个客户端实例中可以适量发出多个请求(总时间应稍小于服务器KeepAliveTimeout参数)。此方式需要精确操作,不推荐。
最后,在接口设计上,对于一些异步操作,尽量不要设计成单方面轮询模式(减少大量无谓请求数),应设计成被调用方的异步结果回调模式。
【一些优化细节】
在服务器端,我们一般选用的是Apache+Tomcat/JBoss的组合。关于JBoss的配置及优化可参看JBoss官网。
最主要的是关于Apache的优化,推荐阅读两篇文章:
1、Apache性能优化:http://www.aliwo.net:8080/2009/12/apache/
2,保持活动的Apache配置中的合理使用:http://www.net527.cn/a/caozuoxitong/Linux/5283.html
在客户端的Java代码中,我们最常使用的是HttpClient工具包。
有一些细节要注意:
1、在每一个HttpClient实例发完请求后,(如不再使用)应及时关闭连接。
最简单的方式是,在HTTP请求头中发送(连接:CLOSE ),指示服务器关闭当前连接。
代码如下:
method.setRequestHeader(“Connectio “,”关闭“);//改了这个,发现性能很差
2、可以设计为单例模式:无需每次创建HttpClient实例,可多次发送请求(请求头设置见第一条)
查看Apache并发连接数及其TCP连接状态
http://koda.iteye.com/blog/1130495
Linux下高并发socket最大连接数所受的各种限制
http://blog.csdn.net/guowake/article/details/6615728
[linux] 查看tcp连接数及状态
http://xukaizijian.blog.163.com/blog/static/170433119201132910162393/