看起来Spring的WebServiceTemplate忽略了连接超时的设置。那,或者我误解了连接超时。
这是我的配置:
@Bean
public SoapTemplate soapTemplate(Jaxb2Marshaller marshaller, WebServiceMessageSender webServiceMessageSender ) {
SoapTemplate template = new SoapTemplate();
template.setDefaultUri("some_url");
template.setMarshaller(marshaller);
template.setUnmarshaller(marshaller);
template.setMessageSender(webServiceMessageSender);
return template;
}
@Bean
public WebServiceMessageSender webServiceMessageSender() {
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
sender.setReadTimeout(5*1000);
sender.setConnectionTimeout(5*1000);
return sender;
}
Soap模板扩展了WebServiceGateway,并具有一些特定的日志记录,自定义异常功能。
当我启动应该接收WebServiceTemplate生成的SOAP消息的目标应用程序时,读取超时按预期工作。如果服务器在指定时间内没有响应,则抛出异常。
我的理解是,如果TCP 3-Way Handshake没有在指定时间内发生,则应该发生连接超时。但事实并非如此,因为超时总是在约2秒后发生,无论我的配置如何。
这是一个有效的测试,还是应该使用在线但不能接受新连接的拥塞服务器测试连接超时?我的客户遇到了哪个超时,可以控制吗?
答案 0 :(得分:1)
这不能解释问题,但HttpComponentsMessageSender的默认构造函数使用不推荐的org.apache.http.impl.client.DefaultHttpClient。尝试使用org.apache.http.client.HttpClient:
@Bean
public HttpComponentsMessageSender webServiceMessageSender() {
final HttpClient httpClient = buildHttpClient(5*1000, 5*1000, 2, true);
final HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(httpClient);
return messageSender;
}
@SuppressWarnings("resource")
private static HttpClient buildHttpClient(final int connectionTimeout, final int socketTimeout, final int retryCount, final boolean trustAll) {
// timeout config
final RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectionTimeout).setSocketTimeout(socketTimeout).build();
// trust all (if selected)
SSLConnectionSocketFactory sslSocketFactory = null;
if (trustAll) {
try {
final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustAllStrategy()).build();
sslSocketFactory = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
throw new RuntimeException("could not initialize SSL context, reason: " + e.getMessage(), e);
}
}
// socket factory
final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", trustAll ? sslSocketFactory : SSLConnectionSocketFactory.getSocketFactory()).build();
// retry handler
final HttpRequestRetryHandler retryHandler = new SimpleRetryHandler(retryCount);
// build client
final HttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig)
.setConnectionManager(new PoolingHttpClientConnectionManager(socketFactoryRegistry)).setRetryHandler(retryHandler)
.addInterceptorFirst(new RemoveSoapHeadersInterceptor()).build();
return httpClient;
}
更新:我们在使用SSL连接的项目中使用了自定义buildHttpClient
方法。如果您不需要SSL部分,请尝试逐步删除它。