setConnectTimeout与setConnectionTimeToLive对比setSocketTimeout()

Ela*_*da2 11 java apache-httpclient-4.x

有谁可以解释这两者之间的区别是什么:

client = HttpClientBuilder.create()
    .setConnectionTimeToLive(1, TimeUnit.MINUTES)
    .build();
Run Code Online (Sandbox Code Playgroud)

RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
client = HttpClientBuilder
    .create()
    .setDefaultRequestConfig(requestConfig)
    .build();
Run Code Online (Sandbox Code Playgroud)

使用起来更好setSocketTimeout吗?

Sky*_*ker 6

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

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

设置连接请求超时:

然而,它是特定于配置连接管理器的。是时候从连接池中获取连接了。

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

设置连接生存时间

公共最终 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;
}
Run Code Online (Sandbox Code Playgroud)

资源链接:

  1. HttpClientStarter.java

  2. HttpClient 4.x 超时

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;
            }
        };
Run Code Online (Sandbox Code Playgroud)

连接驱逐策略

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

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

资源链接:

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


van*_*kel 5

A ConnectTimeout确定在创建新连接时等待对方回答“是的,我在这里,让我们聊一聊”的最长时间(ConnectTimeout最终调用socket.connect(address,timeout)。等待时间通常小于a第二,除非对方真的只是在忙于接受新的传入连接,否则您必须经过中国的防火墙,在后一种情况下,可能需要一分钟(或更长时间)才能创建新的连接。内未建立ConnectTimeout,则会出现错误(1)。

setSocketTimeout最终致电socket.setSoTimeout对此答案有解释。

ConnectionTimeToLive无论何时连接上次使用的确定连接的最大年龄(在此之后它将被关闭)。通常,清理连接有一个“空闲超时”,即您或另一端将关闭一段时间未使用的连接。通常,您将在另一端执行此操作之前关闭空闲连接,以防止发生错误。但是,我可以想到另外两种情况:最大连接期限是有用的:

  • 不良的网络组件:如果您没有遇到过,请算上您的运气。大约30分钟后,某些不良的路由器,防火墙,代理等将仅断开(正在使用)连接。由于您和另一端甚至可能都不知道连接已断开,因此在奇怪的时候,您可能会在没有明显原因的情况下收到“连接重置”错误。
  • 缓存的元数据:大多数系统在某种缓存中保留一些有关连接的元数据。某些系统无法很好地管理此缓存-缓存大小只会随着连接的使用期限而增长。

关于ConnectionTimeToLiveApache HttpClient 4.5.4中实现的说明:我认为您必须使用PoolingHttpClientConnectionManagerfor选项才能起作用(最终所有结果都归结为对该isExpired方法的调用)。如果不使用此连接管理器,请测试该选项以确保它确实有效。

(1)EJP关于此相关答案的有趣评论