setConnectTimeout vs setConnectionTimeToLive与setSocketTimeout()

有人能解释一下这两者之间的区别:

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

RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
client = HttpClientBuilder
    .create()
    .setDefaultRequestConfig(requestConfig)
    .build();

使用setSocketTimeout更好吗?


ConnectTimeout决定在创建新连接时等待另一方回答“是的,我在这里,让我们谈谈”的最长时间( ConnectTimeout最终调用socket.connect(地址,超时)。等待时间通常较少除非另一方真的忙于接受新的传入连接,或者你必须通过中国的伟大防火墙,在后一种情况下,创建新连接之前可能需要一分钟(或更多)。连接没有在ConnectTimeout内建立,你会得到一个错误(1)。

setSocketTimeout最终会调用此答案中解释的socket.setSoTimeout

ConnectionTimeToLive确定ConnectionTimeToLive的最大时间(在此之后它将被关闭),而不管上次连接的使用时间。 通常情况下,清理连接有一个“空闲超时”,即您或另一方将关闭一段时间未使用的连接。 通常情况下,您将在另一方之前关闭空闲连接以防止出现错误。 但是我可以想到另外两种情况:连接的最大年龄在哪里有用:

  • 糟糕的网络组件:如果你没有遇到它们,算你自己幸运。 一些不好的路由器,防火墙,代理等会在30分钟后丢弃(积极使用)连接。 由于你和另一方可能甚至不知道连接被中断,你可以在奇怪的时间出现“连接重置”错误,原因不明。
  • 缓存的元数据:大多数系统在某种缓存中保留一些关于连接的元数据。 一些系统严重地管理这个缓存 - 缓存大小随着连接的时间而增长。
  • 关于Apache HttpClient 4.5.4中的ConnectionTimeToLive实现的一个注意事项:我认为你必须使用PoolingHttpClientConnectionManager来使这个选项起作用(它最终都归结为对这个isExpired方法的调用)。 如果您不使用此连接管理器,请测试该选项以确保它确实有效。

    (1)EJP对这个相关答案的有趣评论


    连接超时:直到建立与服务器的连接时为止的超时时间。

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

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

    资源链接:

  • HttpClientStarter.java

  • 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;
                }
            };
    

    连接驱逐策略

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

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

    资源链接:

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

    链接地址: http://www.djcxy.com/p/86881.html

    上一篇: setConnectTimeout vs. setConnectionTimeToLive vs. setSocketTimeout()

    下一篇: Oracle 12c JSON Query Issue with Dot Notation and Double Quotes