Игнорировать циклический перебор DNS для надежного тайм-аута с Spring-ws и HTTP-клиентом 4.5.x

Мы используем 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);

Есть решение, которое я могу опубликовать, если вопрос снова откроется.

ok2c 30.10.2018 11:18

Мы создаем решение, которое использует многопоточность и синхронизацию для объекта-оболочки result; сделать запрос одним потоком, запланировать другой поток как TimerTask, который запускается через миллисекунды timeout и сигнализирует, что истекло время ожидания запроса. Какой бы поток ни был первым, блокирует объект result и задает объекту result логическое значение didTimeout и результат HTTP-запроса. Просто подумал, что было бы безопаснее, если бы библиотека уже реализовала и протестировала эту функциональность. Каково было ваше решение?

RD_WF 30.10.2018 18:40

Намного проще. Кастомный DnsResolver.

ok2c 31.10.2018 09:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
694
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть два варианта

  1. Сборка собственного ClientConnectionOperator

  2. Сборка собственного DnsResolver. Этот вариант намного проще.

    CloseableHttpClient client = HttpClients.custom()
       .setDnsResolver(host -> new InetAddress[] { InetAddress.getByName(host) })
       .build();
    

Другие вопросы по теме