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了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章