遇到一个问题很棘手两天了还没解决掉,报错如下:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980) ~[na:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363) ~[na:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391) ~[na:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375) ~[na:1.8.0_45]
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563) ~[na:1.8.0_45]
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) ~[na:1.8.0_45]
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153) ~[na:1.8.0_45]
at com.dangdang.ddframe.job.executor.type.SimpleJobExecutor.process(SimpleJobExecutor.java:41) [elastic-job-common-core-2.1.5.jar:na]
at com.dangdang.ddframe.job.executor.AbstractElasticJobExecutor.process(AbstractElasticJobExecutor.java:206) [elastic-job-common-core-2.1.5.jar:na]
at com.dangdang.ddframe.job.executor.AbstractElasticJobExecutor.process(AbstractElasticJobExecutor.java:171) [elastic-job-common-core-2.1.5.jar:na]
at com.dangdang.ddframe.job.executor.AbstractElasticJobExecutor.execute(AbstractElasticJobExecutor.java:150) [elastic-job-common-core-2.1.5.jar:na]
at com.dangdang.ddframe.job.executor.AbstractElasticJobExecutor.execute(AbstractElasticJobExecutor.java:122) [elastic-job-common-core-2.1.5.jar:na]
at com.dangdang.ddframe.job.lite.internal.schedule.LiteJob.execute(LiteJob.java:26) [elastic-job-lite-core-2.1.5.jar:na]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [quartz-2.2.1.jar:na]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.1.jar:na]
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505) ~[na:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:961) ~[na:1.8.0_45]
... 21 common frames omitted
这个是他们用httpclient 调用三方的一个https的接口,在本地单元测试没问题,用浏览打开也没问题。
因为之前遇到类似问题,就很自信的在网络上找相关的解决方案,找了好多方案,例如:System.setProperty(“https.protocols”, “TLSv1,TLSv1.1,TLSv1.2”);
再如:SSLContext sslContext = SSLContext.getInstance(“TLSv1.2”); 都不行。
还有说是jdk 1.7 才会有这个问题,但是我们的环境本身就是1.8. 看着别人的评论通过这些方法多少都解决了问题,我们是真越发的着急了,
想来想去,三方接口没动,环境也没动,我们本地行,测试环境不行,又觉得是环境问题,又看了一下jdk版本,本地是1.8.0_131,测试环境是1.8.0_45 ,想到会不是这个问题,就把本地jdk做了降级到45 ,可悲的是并没有在本地重现测试环境问题,这时候,我们只能怀疑是网络问题,怎么查呢?抓包。
抓包 下来后,我们对比了本地的包,测试环境的包确实发现些问题,测试环境的包截图如下:
tcp三次握手后,客户端发了个 Client hello ,但是服务端确返回了,Handshake Failure 问题肯定是出这里,对比这个包,跟正常的包,反复对比后,还是没能看到问题来,于是找到了网络同事,网络同事也是协助一起查看。
终于找到了这么一个帖子:Java加密套件强度限制引起的SSL handshake_failure 我对比了下,情况几乎一样,我把作者查找问题的方法都试了一遍(验证方法可以参考上面的帖子,不再赘余),也都一致,最终我们尝试了作者给出的方法 :
升级jdk到 1.8.0_151和以后的版本,无需下载任何文件,只要修改Java\jre\lib\security\java.security文件
crypto.policy = unlimited
这次真真的问题解决了,在这里也谢谢这位作者!
到这里还没完,这种方式,还是要修改jdk的配置文件,考虑到线上环境都是统一,修改文件会使得jdk变的不统一,我又尝试着找看看有没有更好的办法,果然,又看到另外一个文章:JCE policy changes in Java SE 8u151, 8u152 and 8u162 文章里说“Oracle released Java 8 u162. In this version the unlimited policy is enabled by default. You no longer need to install the policy file in the JRE or set the security property crypto.policy.”
jdk1.8.0_162 之上的版本已经将crypto.policy 默认设置为unlimited 于是我们索性直接将jdk升级到1.8的最终更新Java SE 8u181 到此问题总算处理完了!
这个bug: JDK-8170157
总结一下:
问题的最终解决,算不上自己一步步解决掉,参考了前人的大多文章,这里想说的是解决问题的方法和思路:
1.一定要坚持,好多问题有些同事,上网找找没有办法就不干了
2.先思考,自己解决,处理不了,多上网找找资料,互联可能是会陪伴我们终生的老师,好好借用
3.这里面用到了好多的网络知识,和处理网络问题的办法,比如,tcp,ssl/tls ,Handshake,抓包等等,可能作为一个开发人员会觉得这些离我们很远,我们跟本用不到,只用java 编码就行了,只会crud,能完成开发功能就可以了,我只能说那么你这一辈子也就只能当个初级程序员!!!