httpclient proxy 方式ssl 死锁 socketRead0问题解决

最近用HttpClient使用代理ip进行链接请求,发现经常有线程hang住,查看线程dump

"pool-7-thread-1" #25 prio=5 os_prio=0 tid=0x00007f65bae19800 nid=0x16a9 runnable [0x00007f6597efb000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:593)
at sun.security.ssl.InputRecord.read(InputRecord.java:532)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
- locked <0x000000077f712618> (a java.lang.Object)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
- locked <0x000000077f7125d8> (a java.lang.Object)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.upgrade(DefaultHttpClientConnectionOperator.java:193)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.upgrade(PoolingHttpClientConnectionManager.java:389)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:416)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
at com.loushi.service.IPPoolService.canUserIP(IPPoolService.java:162)
at com.loushi.service.IPPoolService.getKuaidailiIPList(IPPoolService.java:113)
at com.loushi.service.IPPoolService.updateIPPoolRedisData(IPPoolService.java:52)
at com.loushi.service.ScheduledService.updateIPPoolRedisData(ScheduledService.java:21)
at sun.reflect.GeneratedMethodAccessor65.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

网上找的办法有以下几种:

1:没设置超时时间,本人确认设置了connectionTimeout, socketTimeout 还是无限等待

2:httpclient 4.3.6之前的一个bug,检查发现自己的httpclient是他4.5.3

3:一直就停留在java.net.SocketInputStream.socketRead0 这个Native方法,单步调试了之后发现timeout参数也传入了,后来在网上搜索发现这个是jdk一个bug,检查后发现自己的这个jdk也是修复后的

可参见:https://www.cnblogs.com/lcxdever/p/7481912.html

没办法,思前想后折腾了好几天,还是觉得绕过这个坑,另外写了个多线程去跑,然后每个线程控制执行时间,一旦执行时间超过了设置了,直接把那个线程kill掉,问题解决

原文地址:https://www.cnblogs.com/bestruggle/p/9836749.html