JDK7 socketRead0 无休止挂起原因及解决方法

今天遇到了一个之前从没遇到过的问题:线程执行到SocketInputStream.socketRead0 时就没动静了,一直保持 runnable 状态,等了一个多小时还是这样,后来只好重启服务器来解决了。

在这个线程卡住的时候,通过 jstack 分析了一下线程栈:

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:160)
    at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:84)
    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:273)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261)
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:283)
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:251)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:197)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:882)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)

可以看到,在执行到socketRead0 时线程保持 runnable状态不变了。。

后来debug 一步一步查看问题,在执行 socketRead0 时发现传入的 timeout 竟然为 0,HttpParamConfig.getSocketConfig 默认会将 CoreConnectionPNames.SO_TIMEOUT 赋值为 0 ,Apache HttpClient有个比较坑的地方,如果对方因为网络原因或者其他原因没有返回数据,Apache HttpClient 会一直等待数据直到超时,但若 timeout=0 时则会一直等待下去。

后面在 HttpClient.HttpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,40*1000) 将 timeout设为40S就ok了。

 

你可能感兴趣的:(SpringMVC学习,Java学习,计算机网络)