专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  DeepSeek薪资曝光! ·  昨天  
Java编程精选  ·  SpringBoot 实现 PDF ... ·  3 天前  
芋道源码  ·  代码越“整洁”,性能越“拉胯”? ·  4 天前  
51好读  ›  专栏  ›  ImportNew

Apache HttpClient 没有设置 time out 导致应用长时间阻塞的问题

ImportNew  · 公众号  · Java  · 2017-01-05 20:07

正文

(点击上方公众号,可快速关注)


来源:hengyunabc

链接:blog.csdn.net/hengyunabc/article/details/22716911

如有好文章投稿,请点击 → 这里了解详情


update 2014-5-18:


今天又处理了一个HttpClient阻塞的问题,还是socket read没有超时设置。


用jstack -l pid 得到线程的调用栈,每隔一段时间执行一次,对比三次的thread dump结果,发现有一个线程是三次执行的位置一样的,说明它是阻塞在这里了:


"org.springframework.jms.listener.DefaultMessageListenerContainer#7-1" prio=10 tid=0x00007f345127d800 nid=0x5b4f0 runnable [0x00007f34753d1000]  

   java.lang.Thread.State: RUNNABLE  

    at java.net.SocketInputStream.socketRead0(Native Method)  

    at java.net.SocketInputStream.read(SocketInputStream.java:150)  

    at java.net.SocketInputStream.read(SocketInputStream.java:121)  

    at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:130)  

    at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:127)  

    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:233)  

    at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:220)  

    at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:183)  

    at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:152)  

    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)  

    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)  

    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)  

    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)  

    - locked (a java.io.InputStreamReader)  

    at java.io.InputStreamReader.read(InputStreamReader.java:184)  

    at java.io.Reader.read(Reader.java:140)  

    at org.apache.http.util.EntityUtils.toString(EntityUtils.java:161)


业务的逻辑是接收一个JMS消息,再http请求调用得到处理结果。在http请求处阻塞了,导致后面的消息都不能消息。


———————————————


现在的对外接口一般都是Http + json的,因为简单,语言无关。


Apache HttpClient应该是最常用的Java http组件了。这货有个坑爹的地方,Apache HttpClient如果对方不回应,或者网络原因不返回了,那么HttpClient会一直阻塞。这种情况在公网可能比较容易碰到。在内网时,也有一次因为一台中转的nginx挂掉而导致hessian请求长时间阻塞。


因为Http Client默认的SO_TIMEOUT是0,即一直等待。


这个问题,在帮同事查找问题时碰到好几次了,可能是大家潜意识里认为Http请求是即时的,失败的话也很快返回。


Apache HttpClient的示例也没提到要设置TimeOut,这也是比较坑爹的地方。一个库如果没有默认阻止用户去范错误,那么你也应当在文档,示例代码里提醒用户不要范错误。


有三个可以设置time out 的参数:


httpClient = new DefaultHttpClient();  

httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_LINGER, value)  

httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 3000);  

httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000);


SO_LINGER最好不要设置,可能会坑死人。


参考:


  • http://unliminet.blog.51cto.com/380895/346686


  • http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required


觉得本文对你有帮助?请分享给更多人

关注「ImportNew」,看技术干货