问题描述
最近,公司生产环境一个运行了很久的老项目突然发生大量相同报错。简单说就是通过HttpClient调用某第三方服务商的所有接口,一直提示Connection reset。
message:ECEPTION cn.hutool.core.io.IORuntimeException:
SocketException: Connection reset
问题分析
- 首先想到的是服务商的网络不通,或者更改了黑名单、白名单之类的限制。
联系服务商,对方说网络正常,系统最近也没有变动过。联系系统运维curl对方的接口,发现正常返回。可以排除掉网络的原因。
- 然后考虑是不是我们自己做了什么改动,导致这个问题。
检查最近系统的发布记录,和这个报错没有关联。可以排除掉代码的原因 。
运维这边也确定服务器的配置也没有改过。那问题来源又可以把我们排除。
问题解决
- 既不是服务商网络的问题,也不是我们的问题,一下子没有了思路。百度,google一直也查不到原因。
- 运气好的是,我本地启动项目去调用第三方服务商接口的时候,无意中使用了1.8版本的JDK(这个项目生产的JDK版本是1.7)。然后调用接口成功了。说明这个问题是和JDK版本有关的。
- 按照这个思路,查找资料。很快,我就怀疑是服务商更新了https的ssl证书,新的证书不支持TLSV1.0。因为JDK1.7默认使用的TLS版本是1.0,所以出现了这个问题。而我本地使用了JDK1.8,所以访问正常。
- 最后让运维在生产的JVM启动参数加上**-Dhttps.protocols=TLSv1.2**,把默认的TLS版本指定为1.2,成功解决。联系服务商,最后果然是因为他们更新了SSL证书。
总结
服务端更改SSL证书,导致不支持TLSV1.0。客户端JDK版本是1.7,默认TLS版本是1.0,所以访问服务端报错Connection reset。要在JVM启动参数增加-Dhttps.protocols=TLSv1.2,来解决问题。