Мы используем Http Client 4.5.x с Spring-Ws и делаем запросы с помощью метода webServiceTemplate.marshalSendAndReceive(requestObject). Мы хотели бы иметь надежное значение тайм-аута соединения, но в настоящее время сталкиваемся с описанной проблемой здесь, в разделе 8 (циклический перебор DNS), когда пробуются несколько IP-адресов, и поэтому тайм-аут непредсказуем. Есть ли простые способы установить жесткий тайм-аут по прошествии определенного времени, используя только Spring-ws и клиентскую библиотеку Http, или требуется установка какого-то настраиваемого тайм-аута?
Случай: тайм-аут подключения установлен на 1 секунду (фактический тайм-аут для метода составляет 4 секунды - можно ли установить тайм-аут метода в 1 секунду с помощью клиентской библиотеки Spring / Http?)
Журналы приложений (для журналов HTTP-клиента установлено значение DEBUG):
16:45:02 (org.apache.http.impl.execchain.MainClientExec) Opening connection {}->http://salesforce.com:448
16:45:02 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connecting to salesforce.com/96.43.149.26:448
16:45:03 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connect to salesforce.com/96.43.149.26:448 timed out. Connection will be retried using another IP address
16:45:03 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connecting to salesforce.com/96.43.145.26:448
16:45:04 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connect to salesforce.com/96.43.145.26:448 timed out. Connection will be retried using another IP address
16:45:04 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connecting to salesforce.com/96.43.144.26:448
16:45:05 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connect to salesforce.com/96.43.144.26:448 timed out. Connection will be retried using another IP address
16:45:05 (org.apache.http.impl.conn.DefaultHttpClientConnectionOperator) Connecting to salesforce.com/96.43.148.26:448
16:45:06 (org.apache.http.impl.conn.DefaultManagedHttpClientConnection) http-outgoing-0: Shutdown connection
Клиентский компонент HTTP:
<bean id = "httpClientBean" class = "org.apache.http.client.HttpClient" factory-bean = "httpClientFactory" factory-method = "getHttpClient" />
Заводской код Http (значение тайм-аута подключения устанавливается с помощью инъекции зависимостей Spring):
public class HttpFactory {
private int connectionTimeout;
public HttpFactory(int connectionTimeout, ...) {
this.connectionTimeout = connectionTimeout;
...
}
...
public HttpClient getHttpClient() {
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
...
RequestConfig.Builder configBuilder = RequestConfig.custom();
configBuilder.setConnectTimeout(this.connectionTimeout);
clientBuilder.setDefaultRequestConfig(configBuilder.build());
...
return clientBuilder.build();
}
}
Компонент шаблона веб-службы:
<bean id = "webServiceTemplate" class = "org.springframework.ws.client.core.WebServiceTemplate">
...
<property name = "messageSender">
<bean class = "org.springframework.ws.transport.http.HttpComponentsMessageSender">
<constructor-arg index = "0">
<ref bean = "httpClientBean" />
</constructor-arg>
</bean>
</property>
</bean>
Сервисный код (мы хотим, чтобы вызов этого метода занимал X секунд, а не 2 или 3 секунды):
// we want this method call to take ~1 second, not ~4 seconds (i.e. similar to the connection timeout value, not a multiplier)
Object obj = webServiceTemplate.marshalSendAndReceive(requestDocument);
Мы создаем решение, которое использует многопоточность и синхронизацию для объекта-оболочки result; сделать запрос одним потоком, запланировать другой поток как TimerTask, который запускается через миллисекунды timeout и сигнализирует, что истекло время ожидания запроса. Какой бы поток ни был первым, блокирует объект result и задает объекту result логическое значение didTimeout и результат HTTP-запроса. Просто подумал, что было бы безопаснее, если бы библиотека уже реализовала и протестировала эту функциональность. Каково было ваше решение?
Намного проще. Кастомный DnsResolver.




Есть два варианта
Сборка собственного ClientConnectionOperator
Сборка собственного DnsResolver. Этот вариант намного проще.
CloseableHttpClient client = HttpClients.custom()
.setDnsResolver(host -> new InetAddress[] { InetAddress.getByName(host) })
.build();
Есть решение, которое я могу опубликовать, если вопрос снова откроется.