Apache HttpClient CoreConnectionPNames.CONNECTION_TIMEOUT ничего не делает? - PullRequest
4 голосов
/ 08 июня 2010

Я получаю странное поведение от HttpClient с параметром CoreConnectionPNames.CONNECTION_TIMEOUT, установленным в 1. Я ожидал бы, что запрос HttpGet завершится неудачно, выбрасывая исключение тайм-аута соединения, и все же они успешны. Это кажется иррациональным, поскольку фактически означает, что TCP-рукопожатие завершилось менее чем за 1 миллисекунду.

Версия httpclient, которую я использую, как видно из этого pom.xml:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.0.1</version>
        <type>jar</type>
    </dependency>

Вот код:

import java.io.IOException;
import java.util.Random;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

public class TestNodeAliveness {
    private static Logger log = Logger.getLogger(TestNodeAliveness.class);

    public static boolean nodeBIT(String elasticIP) throws ClientProtocolException, IOException {
        try {
            HttpClient client = new DefaultHttpClient();

            // The time it takes to open TCP connection.
            client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 1);

            // Timeout when server does not send data.
            client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);

            // Some tuning that is not required for bit tests.
            client.getParams().setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
            client.getParams().setParameter(CoreConnectionPNames.TCP_NODELAY, true);


            HttpUriRequest request = new HttpGet("http://" + elasticIP);
            HttpResponse response = client.execute(request);

            HttpEntity entity = response.getEntity();
            if(entity == null) { 
                return false;
            } else {
                System.out.println(EntityUtils.toString(entity));
            }

            // Close just in case.
            request.abort();

        } catch (Throwable e) {
            log.warn("BIT Test failed for " + elasticIP);
            e.printStackTrace();

            return false;
        }

        return true;
    }


    public static void main(String[] args) throws ClientProtocolException, IOException {
        nodeBIT("google.com?cant_cache_this=" + (new Random()).nextInt());
    }
}

Как это возможно? Спасибо.

Ответы [ 2 ]

5 голосов
/ 10 июня 2010

Эффективная гранулярность тайм-аутов во всех JVM, с которыми я работал, составляет приблизительно 15-30 мс.Даже если для тайм-аута установлено значение 1 сокет ввода-вывода и запросы на подключение часто выполняются успешно, если они занимают менее 15-30 мс.

1 голос
/ 10 декабря 2014

Если вы установите тайм-аут HttpGet вместо HttpClient, он будет работать намного лучше.

    HttpGet httpget = new HttpGet("http://www.apache.org/");

    RequestConfig Default = RequestConfig.DEFAULT;

    RequestConfig requestConfig = RequestConfig.copy(Default)
            .setSocketTimeout(5000)
            .setConnectTimeout(5000)
            .setConnectionRequestTimeout(5000)
            .build();
    httpget.setConfig(requestConfig);
...