setConnectTimeout与setConnectionTimeToLive对比setSocketTimeout()

时间:2015-07-22 14:58:43

标签: java apache-httpclient-4.x

有人可以解释一下这两者之间有什么区别:

foreach

client = HttpClientBuilder.create()
    .setConnectionTimeToLive(1, TimeUnit.MINUTES)
    .build();

使用RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build(); client = HttpClientBuilder .create() .setDefaultRequestConfig(requestConfig) .build(); 是否更好?

2 个答案:

答案 0 :(得分:5)

ConnectTimeout确定等待对方回答的最长时间"是的,我在这里,让我们说话"在创建新连接时(ConnectTimeout最终调用socket.connect(address, timeout)。等待时间通常不到一秒,除非另一方真的忙于接受新的传入连接或者你必须通过中国的防火墙很好。在后一种情况下,在创建新连接之前可能需要一分钟(或更长时间)。如果在ConnectTimeout内未建立连接,则会出现错误(1)。

setSocketTimeout最终会调用socket.setSoTimeout中解释的this answer

ConnectionTimeToLive确定连接的最大年龄(之后将关闭),无论上次使用何时连接。通常,有一个"空闲超时"清理连接,即您或另一方将关闭一段时间未使用的连接。通常,您将在另一方执行之前关闭空闲连接以防止错误。但是我还可以考虑另外两种情况,即连接的最大年龄在哪里有用:

  • 糟糕的网络组件:如果你还没有遇到它们,那就算好自己。一些糟糕的路由器,防火墙,代理等将在30分钟之后丢弃(主动使用)连接。由于您和另一方可能甚至不知道连接被丢弃,您可以获得"连接重置"在奇怪的时候没有明显原因的错误。
  • 缓存的元数据:大多数系统会在某种缓存中保留一些关于连接的元数据。有些系统严重管理这个缓存 - 缓存大小随着连接的年龄而增长。

关于Apache HttpClient 4.5.4中ConnectionTimeToLive实现的说明:我认为你必须使用PoolingHttpClientConnectionManager来使用该选项(它最终都归结为对{{3}的调用} 方法)。如果您不使用此连接管理器,请测试该选项以确保它确实有效。

(1)EJP对this isExpired

的有趣评论

答案 1 :(得分:3)

连接超时: 在建立与服务器的连接之前是超时。

套接字超时: 这是等待数据包[数据]接收的不活动时间。

<强> setConnectionRequestTimeout:

但是它特定于配置连接管理器。现在是从连接池获取连接的时候了。

它返回从连接管理器请求连接时使用的超时(以毫秒为单位)。 0(零)用于无限超时。

setConnectionTimeToLive

  

public final HttpClientBuilder setConnectionTimeToLive(long connTimeToLive,TimeUnit connTimeToLiveTimeUnit)

     

设置持久连接的最长生存时间

     

请注意setConnectionManager(org.apache.http.conn.HttpClientConnectionManager)方法可以覆盖此值。

     

自:   4.4

示例:HttpClientStarter.java

@Override
public boolean start() {

    RegistryBuilder<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory> create();

    // Register http and his plain socket factory
    final SocketFactory ss = getLevel().find(SocketFactory.class);
    ConnectionSocketFactory plainsf = new PlainConnectionSocketFactory() {
        @Override
        public Socket createSocket(HttpContext context) throws IOException {
            return ss.createSocket();
        }
    };
    r.register("http", plainsf);

    // Register https
    ConnectionSocketFactory sslfactory = getSSLSocketFactory();
    if (sslfactory != null) {
        r.register("https", getSSLSocketFactory());
    } else {
        log(Level.WARN, "ssl factory not found, won't manage https");
    }

    HttpClientBuilder builder = HttpClientBuilder.create();
    builder.setUserAgent(USERAGENT);
    builder.setConnectionTimeToLive(timeout, TimeUnit.SECONDS);
    builder.evictIdleConnections((long) timeout, TimeUnit.SECONDS);

    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r.build());
    cm.setMaxTotal(maxConnect * 2);
    cm.setDefaultMaxPerRoute(2);
    cm.setValidateAfterInactivity(timeout * 1000);
    builder.setConnectionManager(cm);

    RequestConfig rc = RequestConfig.custom()
            .setConnectionRequestTimeout(timeout * 1000)
            .setConnectTimeout(timeout * 1000)
            .setSocketTimeout(timeout * 1000)
            .build();
    builder.setDefaultRequestConfig(rc);

    client = builder.build();

    return true;
}

资源链接:

  1. HttpClientStarter.java

  2. HttpClient 4.x Timeout

  3. HTTP规范不确定持久连接可能或应该保持活动的时间长度。某些HTTP服务器使用非标准标头Keep-Alive来告诉客户端他们希望在服务器端保持连接的秒数。如果此信息可用,HttClient将利用此功能。如果响应中不存在标题信息Keep-Alive,则HttpClient会假定连接无限期保持活动状态。但是,许多真实的HTTP服务器配置为在一段时间不活动后丢弃持久连接以节省系统资源,通常不会通知客户端。

    在这里你可以重写一个,这里设置为5秒

    ConnectionKeepAliveStrategy keepAliveStrategy = new DefaultConnectionKeepAliveStrategy() {
                @Override
                public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {
                    long keepAlive = super.getKeepAliveDuration(response, context);
                    if (keepAlive == -1) {
                        keepAlive = 5000;
                    }
                    return keepAlive;
                }
            };
    

    连接驱逐政策

      

    经典的阻塞I / O模型的主要缺点是网络   仅当I / O操作被阻止时,套接字才会响应I / O事件。   当连接释放回管理器时,可以保留它   在没有监视套接字状态和响应的情况下生存   任何I / O事件。如果在服务器端关闭连接,那么   客户端连接无法检测连接状态的变化   并关闭本地套接字以正确响应。

    HttpClient尝试通过测试连接是否过时来缓解此问题,该连接已不再有效,因为在使用发出HTTP请求的连接之前,连接已在服务器端关闭。过时的连接检查不是100%稳定,而是每次请求执行需要10到30毫秒。唯一可行的套接字模型线程解决方案不涉及每个空闲连接,即使用专用监视线程来回收由于长时间不活动而被视为过期的连接。监控线程可以定期调用ClientConnectionManager#closeExpiredConnections()方法关闭所有过期的连接,退出连接池关闭连接。它还可以选择调用ClientConnectionManager#closeIdleConnections()方法来关闭已经空闲超过给定时间段的所有连接。

    资源链接:

    http://dev.dafan.info/detail/513285