I've been looking into an issue with TLS handshake timeouts on the async client (see https://github.com/apache/httpcomponents-client/pull/118), and I think that this topic might benefit from a broader audit.
Currently, there are three types of timeouts we expose through RequestConfig: 1. Connection request timeout (defined as the time to wait when requesting a connection from the connection manager) 2. Connect timeout (defined as the time to wait until a new connection is fully established) 3. Response timeout (defined as the time to wait until arrival of a response from the opposite endpoint); this is basically a reboot of the "socket timeout" value exposed in previous versions Since all of these definitions are fairly high-level, they are tricky to implement correctly in terms of low-level IO timeouts. For example, implementing a connection timeout in terms of a socket timeout has surprising implications, because establishing a TLS connection requires multiple operations on the socket (TCP handshake, followed by two round trips for the TLS handshake). If I specify a connection timeout of 2.5 seconds, and each round trip to the remote host takes 2 seconds, will the connection attempt actually time out as it ought to? (This scenario can be made almost arbitrarily complicated by adding proxy hops to the route, HTTP auth challenge/response steps, and so forth.) A similar point applies to the response timeout: the definition is somewhat ambiguous, because "the arrival of a response" can be interpreted as (1) the initial bytes of the response, (2) the end of the response, or (3) the next packet of the response (i.e. max wait time per read operation, which is basically the definition of socketTimeout). These definitions are only approximately the same in the case of relatively short and simple responses, not long-running streams. Interactions are another subtlety: timeouts can interact with each other, as well as with other client features. Is the connection request considered part of the connection phase, or are they logically separate? Is it meaningful for the connection request timeout to be longer than the request timeout? If I hit the connectionTimeout, what does the DefaultHttpRequestRetryHandler do? Finally, there's the question of synchronous versus asynchronous IO. Do we expect to be able to implement the exact same timeout behavior on NIO and BIO, or will we have to make compromises somewhere? --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
