Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache HttpClient: setConnectTimeout() vs. setConnectionTimeToLive() vs. setSocketTimeout()

Can someone please explain what is the difference between these two:

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

and

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

Is it better to use setSocketTimeout()?

like image 816
Elad Benda2 Avatar asked Jul 22 '15 14:07

Elad Benda2


People also ask

What is setConnectionTimeToLive?

public final HttpClientBuilder setConnectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) Sets maximum time to live for persistent connections. Please note this value can be overridden by the setConnectionManager(org. apache.

What is the difference between connection timeout and connection request timeout?

request timeout — a time period required to process an HTTP call: from sending a request to receiving a response. connection timeout — a time period in which a client should establish a connection with a server.

How do I set the connection timeout in HTTP client?

The default value is 100,000 milliseconds (100 seconds). To set an infinite timeout, set the property value to InfiniteTimeSpan. A Domain Name System (DNS) query may take up to 15 seconds to return or time out.

What is connectionRequestTimeout?

connectTimeout is the timeout until a connection with the server is established. connectionRequestTimeout is used when requesting a connection from the connection manager.


2 Answers

A ConnectTimeout determines the maximum time to wait for the other side to answer "yes, I'm here, let's talk" when creating a new connection (ConnectTimeout eventually calls socket.connect(address, timeout). The wait-time is usually less than a second, unless the other side is really busy with just accepting new incoming connections or you have to go through the great firewall of China. In the latter cases it can be a minute (or more) before the new connection is created. If the connection is not established within the ConnectTimeout, you get an error (1).

setSocketTimeout eventually calls socket.setSoTimeout which is explained in this answer.

The ConnectionTimeToLive determines the maximum age of a connection (after which it will be closed), regardless of when the connection was last used. Normally, there is an "idle timeout" to cleanup connections, i.e. you or the other side will close a connection that is not used for a while. Typically, you will close an idle connection before the other side does to prevent errors. But there are two other cases I can think of where a maximum age for a connection is useful:

  • Bad network components: count yourself lucky if you have not met them. Some bad routers, firewalls, proxies, etc. will just drop (actively being used) connections after something like 30 minutes. Since you and the other side may not even be aware that a connection was dropped, you can get "connection reset" errors for no obvious reason at weird times.
  • Cached meta-data: most systems keep some meta-data about a connection in some sort of cache. Some systems manage this cache badly - cache size just grows with the age of the connection.

A note about the ConnectionTimeToLive implementation in Apache HttpClient 4.5.4: I think you must use the PoolingHttpClientConnectionManager for the option to work (it eventually all comes down to a call to this isExpired method). If you do not use this connection manager, test the option to make sure it really works.

(1) Interesting comment from EJP user207421 on this related answer

like image 100
vanOekel Avatar answered Sep 18 '22 17:09

vanOekel


Connection Timeout: It is the timeout until a connection with the server is established.

Socket Timeout: this is the time of inactivity to wait for packets[data] to receive.

setConnectionRequestTimeout:

However it is specific for configuring the connection manager. It is the time to fetch a connection from the connection pool.

It returns the timeout in milliseconds used when requesting a connection from the connection manager. 0(zero) is used for an infinite timeout.

setConnectionTimeToLive

public final HttpClientBuilder setConnectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit)

Sets maximum time to live for persistent connections

Please note this value can be overridden by the setConnectionManager(org.apache.http.conn.HttpClientConnectionManager) method.

Since: 4.4

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

Resource Link:

  1. HttpClientStarter.java

  2. HttpClient 4.x Timeout

The HTTP specification does not determine how long a persistent connection may or should remain active. Some HTTP servers use a non-standard header, Keep-Alive, to tell clients the number of seconds they want to stay connected on the server side. HttClient will take advantage of this if this information is available. If the header information Keep-Alive does not exist in the response, HttpClient assumes the connection remains active indefinitely. However, many real-world HTTP servers are configured to discard persistent connections after certain periods of inactivity to conserve system resources, often without notification to the client.

Here you can rewrite one, here is set to 5 seconds

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

Connection eviction policy

The main disadvantage of a classic blocking I/O model is that network sockets respond to I/O events only when I/O operations are blocked. When a connection is released back to the manager, it can be kept alive without monitoring the status of the socket and responding to any I/O events. If the connection is closed on the server side, then the client connection can not detect changes in the connection status and shut down the local socket to respond properly.

HttpClient tries to alleviate this problem by testing if the connection is outdated, which is no longer valid as it is already closed on the server side before using the connection that made the HTTP request. Outdated connection check is not 100% stable, but instead requires 10 to 30 milliseconds for each request execution. The only workable socket model thread solution that does not involve every free connection is to use a dedicated monitoring thread to reclaim the connection that is considered expired because of prolonged inactivity. Monitoring thread can periodically call ClientConnectionManager#closeExpiredConnections() method to close all expired connections, withdraw from the connection pool closed connection. It can also optionally call the ClientConnectionManager#closeIdleConnections() method to close all connections that have been idle for more than a given period of time.

Resource Link:

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

like image 27
SkyWalker Avatar answered Sep 20 '22 17:09

SkyWalker