Apache HttpClient CoreConnectionPNames.CONNECTION_TIMEOUT 什么都不做?

发布于 2024-09-04 08:55:56 字数 2634 浏览 2 评论 0原文

我从 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());
    }
}

这怎么可能? 谢谢。

I get strange behavior from HttpClient with parameter CoreConnectionPNames.CONNECTION_TIMEOUT set to 1.
I would expect that HttpGet request would fail, throwing connection timeout exception and yet they are successful. This seems irrational as it actually means that TCP handshake finished in less then 1 millisecond.

The httpclient version I'm using as can be seen in this pom.xml is

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

Here is the code:

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());
    }
}

How is this possible?
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神魇的王 2024-09-11 08:55:56

我使用过的所有 JVM 的有效超时粒度约为 15-30 毫秒。即使超时设置为 1 个套接字 I/O,如果连接请求花费的时间少于 15-30 毫秒,则通常会成功。

The effective granularity of time-outs in all JVMs I have worked with is approximately 15-30ms. Even if the timeout is set to 1 socket I/O and connect requests often succeed if they take less than 15-30ms.

最单纯的乌龟 2024-09-11 08:55:56

如果你设置 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);

If you set the timeout of the HttpGet,instead of the HttpClient, it seems to work much better.

    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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文