Игнорировать циклический перебор DNS для надежного тайм-аута с помощью Spring-ws и Http-клиента 4.5.x - PullRequest
0 голосов
/ 27 октября 2018

Мы используем Http Client 4.5.x с Spring-Ws и делаем запросы методом webServiceTemplate.marshalSendAndReceive(requestObject).Нам бы хотелось иметь надежное значение тайм-аута соединения, но в настоящее время мы сталкиваемся с проблемой, описанной здесь, в разделе 8 (циклический перебор DNS) , когда используются несколько IP-адресов, и поэтому тайм-аут непредсказуем.Существуют ли простые способы установки жесткого тайм-аута через определенное время, используя только библиотеку Spring-ws и Http Client, или необходима какая-то особая тайм-аут?


Случай: подключениеТайм-аут установлен на 1 секунду (фактический тайм-аут для метода составляет 4 секунды - возможно ли установить тайм-аут метода на 1 секунду с помощью клиентской библиотеки Spring / Http?)

Журналы приложений (для журналов Http Client установлено значение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 шаблона веб-службы:

    <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 секунд, а не 2x или 3x секунды):

// 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);

1 Ответ

0 голосов
/ 05 ноября 2018

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

  1. Создание пользовательских ClientConnectionOperator

  2. Создание пользовательских DnsResolver. Эта опция намного проще.

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