问题:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://www.xxxx.com/xxxx/xxxx/xxxx": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
本地环境信息:Mac OS 10.14.5、JDK8
测试环境信息:Docker Linux 3.10+、JDK8
场景:
今天有一个功能,需要调用远程API,使用的是RestTemplate,在本地单元测试调用无误后放到测试环境,发生了 read time out 的行为。
排查:
1.首先本地重试,并没有发生超时的timeout。
2.联想到由于是https请求,可能由于https证书的问题,于是配置了信任所有证书。(代码放最后)
3.代码里配置了信任所有证书,响应就正常了。
Conclusion
具体也没有很深入的了解,本地debug时,看到SSL握手之后服务端有返回证书,构造成X509对象,所以证书验证时是通过的,具体可以看:org.apache.http.conn.ssl.SSLConnectionSocketFactory#verifyHostname 方法
由于没有在Linux上跑,所以没有得到最终的结论,mark一下吧。
@Bean
public RestTemplate restTemplate (RestTemplateBuilder builder) throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts =new TrustManager[] {
new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sslContext =SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
CloseableHttpClient httpClient =HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpComponentsClientHttpRequestFactory customRequestFactory =new HttpComponentsClientHttpRequestFactory();
customRequestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = builder.requestFactory(() ->customRequestFactory)
.build();
return builder.build();
}
网友评论