In fact, there are a large number of articles on the Internet to discuss HTTP long connection, and Idle Timeout and KeepAlive Timeout are things on the HTTP protocol, with itself does not have much to do, only recently encountered some problems in the project, used HttpClient, simply summarize, leaving themselves to do future reference.
When using the HttpClient, you can use theHttpClientOptions
Configuring KeepAlive Timeout and the Behavior of Idle Timeout, this article discusses the setting of Idle Timeout in HttpClient, how to enable and disable KeepAlive, and if KeepAlive is enabled, the impact of its timeout setting (Timeout) on keeping HTTP connections alive.
It is important to note that this isClient SettingsThe server side is not discussed in depth here due to the variety of implementation techniques. In this article, KeepAlive has been enabled on the default server side (and is in fact the default behavior of most HTTP servers).
The scenarios discussed in this article only apply to HTTP/1.1, HTTP/1.0 handles KeepAlive slightly differently, HTTP/1.1 supports KeepAlive by default, HTTP/1.0 needs to explicitly add Connection: keep-alive to the header.
Scenario Exercise
Here we set up multiple scenarios to test what the behavior of the whole system behaves like in different situations.
Scenario 1: HttpClient Disabling KeepAlive
HttpClientOptions
Additionally, you can use thesetKeepAlive(false)
to disable KeepAlive:
final HttpClientOptions options = new HttpClientOptions()
.setKeepAlive(false);
In this case, the Http Client will add the following to the request headerconnection: close
, indicating that after completing the flow of an HTTP request/response, theserver-sideA proactive connection closure request needs to be initiated:
Wireshark packet capture analysis:
- HttpClient uses port 60489 to establish a connection with the server (SYN), the server responds with a (SYN, ACK) packet agreeing to establish the connection
- HttpClient sends an HTTP request to the server, which processes the request and returns the
- Since HttpClient makes HTTP requests using the
connection: close
So the server takes the initiative to initiate (FIN, ACK) packets, indicating that the server has closed the connection, the client gets the packet, returns ACK to indicate confirmation, and then also sends (FIN, ACK) to the server, indicating that the client has also closed the connection, and finally the server returns ACK to indicate confirmation.
Scenario 2: HttpClient Enables KeepAlive
HttpClientOptions
Additionally, you can use thesetKeepAlive(false)
to disable KeepAlive:
final HttpClientOptions options = new HttpClientOptions()
.setKeepAliveTimeout(15)
.setKeepAlive(true);
At this point, the Http Client does not send theconnection: close
header, since HTTP/1.1 uses long connections by default, there is no need to specify any additional request headers. After the KeepAlive timeout, the request header is specified by theclient (computing)Actively closes the HTTP connection.
Wireshark packet capture analysis:
- HttpClient uses port 60937 to establish a connection with the server (SYN), the server responds with a (SYN, ACK) packet agreeing to establish a connection
- HttpClient sends an HTTP request to the server, which processes the request and returns the
- HttpClient waits for about 15 seconds (15 seconds set by setKeepAliveTimeout in the above code), since there are no new HTTP requests to occupy the connection, it initiates (FIN, ACK) packet to the server side, indicating that the client has closed the connection, the server side gets the packet, returns ACK to indicate confirmation, and then also sends (FIN, ACK) to the The client sends a (FIN, ACK) packet to the server, indicating that the client has also closed the connection, and finally the client returns an ACK, indicating confirmation
If the server-side KeepAlive Timeout is greater than the HttpClient's KeepAlive Timeout, then when no HTTP requests are made for a period of time, before the HttpClient KeepAlive first times out, the HTTP connection can be reused until the HttpClient KeepAlive times out byclient (computing)Initiates a request to close the connection:
- As you can see, the connection on client port 63094 has been reused for multiple HTTP requests
- Within 15 seconds, there are no new HTTP requests and the client initiates a disconnect packet
If the server-side KeepAlive Timeout is less than the HttpClient's KeepAlive Timeout (e.g., the server-side KeepAlive Timeout is 10s), then when no HTTP requests are made for a period of time, theserver-sidewill first initiate a close connection request:
- HttpClient uses port 64282 to establish a connection with the server (SYN), the server responds with a (SYN, ACK) packet, agreeing to establish the connection
- HTTP connection reused during multiple HTTP requests
- After 10 seconds have passed, the server first initiates a request to close the connection
- After that, the client makes another HTTP request and a new HTTP connection is created.
Scenario 3: HttpClient using both Idle Timeout and KeepAlive Timeout
To simulate such a scenario, the HttpClient is created using the followingHttpClientOptions
:
final HttpClientOptions options = new HttpClientOptions()
.setIdleTimeout(5)
.setIdleTimeoutUnit()
.setKeepAliveTimeout(20)
.setKeepAlive(true);
Then have the server wait 7 seconds before returning the HTTP Response:
[HttpGet(Name = "GetWeatherForecast")]
public async Task<IEnumerable<WeatherForecast>> Get()
{
await (7000);
return (1, 5).Select(index => new WeatherForecast
{
Date = ((index)),
TemperatureC = (-20, 55),
Summary = Summaries[()]
})
.ToArray();
}
Wireshark packet capture analysis:
- establish a connection
- Send the request, the server starts to process the request, it takes 7 seconds to process the request
- After 5 seconds, the client Idle Timeout, can not afford to wait, to the server to initiate the closure of the connection, the server response to close the connection
- For the next request, a new connection needs to be established
Thus, the two settings can be understood in this way:
-
Short Idle Timeout and Long KeepAlive Timeout: If
IdleTimeout
is set shorter, and theKeepAliveTimeout
Set it longer and the connection will close due to the Idle Timeout. Therefore, when a new HTTP request comes in, a new connection needs to be established. -
Long Idle Timeout and Short KeepAlive Timeout: If
IdleTimeout
is set longer, and theKeepAliveTimeout
Set to a shorter time, during the Keep-Alive validity time, even if there is a request on the current connection waiting for a response, the connection can still receive new HTTP requests until the Keep-Alive timeout is triggered. - If an HTTP request is on an HTTP connection waiting for the server to return, the HTTP connection is still active and does not trigger a KeepAlive countdown
In , RequestOptions has a similar setIdleTimeout method to set the Idle Timeout, but its scope is limited to the current HTTP request, and the scope is global to the entire application.
Scenario 4: Sending an HTTP request when KeepAlive is about to expire on the server side
Still using the above [Scenario 2] environment settings, just let the client send a request every KeepAlive Timeout the same time, will find that, in most cases, the request can be successful, but sometimes an error will occur. For example, if the server-side KeepAlive Timeout is 10 seconds, the client also sends requests every 10 seconds:
- Establish a connection and send an HTTP request, the server side responds normally
- After 10 seconds, the client sends a request again, and the server ACKs the request, but at the same time, the server KeepAlive times out, so it sends a (RST, ACK) packet to the client to reset the connection (abnormally closes the connection), at which point the client reports an error:
SEVERE: Connection reset
summarize
- Whether or not an HTTP connection can be reused depends on both the client's and server's KeepAlive behavior
- KeepAlive is usually enabled by default on the server side, and it also has a default value (which varies from server to server implementation)
- Clients can choose whether to enable HTTP connection reuse (enable or disable KeepAlive)
- In HTTP/1.0, to enable it, you need to add to the Request Header the
Connection: keep-alive
The default is disabled.
- In HTTP/1.1, when disabled, the Request Header needs to include the
Connection: close
The default is enabled.
- If the client disables it, the HTTP connection is not reused and a new HTTP connection is created for each request
- If enabled on the client side and the client KeepAlive Timeout (ckt) is less than the server-side KeepAlive Timeout (skt), the
min(ckt, skt)
time period if there are no new HTTP requests and the HTTP connection is idle.client (computing)Will initiate HTTP connection closure
- If enabled on the client side and the client KeepAlive Timeout (ckt) is greater than the server-side KeepAlive Timeout (skt), the
min(ckt, skt)
time period if there are no new HTTP requests and the HTTP connection is idle.server-sideWill initiate HTTP connection closure
- When an HTTP request is sent to the server, the server needs some time to process, HTTP Client sets Idle Timeout, which allows the client to close the HTTP connection when the server does not respond within a certain period of time. Before the client closes the connection due to Idle Timeout, the HTTP request is still waiting for the server's return, and the HTTP connection that carries the HTTP request can still continue to accept other HTTP requests.
- When the server takes a certain amount of time to process an HTTP request, if this processing time happens to be comparable to the server's KeepAlive Timeout, theIt is possible for an HTTP connection to be closed abnormally causing the client to report an error.. Common Solutions:
- Try to avoid making requests when the server-side KeepAlive times out (adjust KeepAlive parameters or customize HTTP request initiation policies as appropriate)
- Retesting mechanism
- Ensure that client-side and server-side timeouts are set appropriately and adjusted accordingly
Relationship between KeepAlive Timeout and Idle Timeout
- In HTTP/1.0, to enable it, you need to add to the Request Header the
Connection: keep-alive
The default is disabled. - In HTTP/1.1, when disabled, the Request Header needs to include the
Connection: close
The default is enabled.
min(ckt, skt)
time period if there are no new HTTP requests and the HTTP connection is idle.client (computing)Will initiate HTTP connection closuremin(ckt, skt)
time period if there are no new HTTP requests and the HTTP connection is idle.server-sideWill initiate HTTP connection closure- Try to avoid making requests when the server-side KeepAlive times out (adjust KeepAlive parameters or customize HTTP request initiation policies as appropriate)
- Retesting mechanism
- Ensure that client-side and server-side timeouts are set appropriately and adjusted accordingly
The two are separate settings, but may interact in certain situations. For example, if theIdleTimeout
The set time is longer than theKeepAliveTimeout
short, then the connection may be closed due to an idle timeout, even though Keep-Alive allows longer connection multiplexing.
Best Practices (referenced from ChatGPT)
-
Adjustment to application requirements:
- If the application needs to reuse connections frequently, you can set a long
KeepAliveTimeout
。 - If you need to prevent the connection from being idle for long periods of time, you can set a short
IdleTimeout
。
- If the application needs to reuse connections frequently, you can set a long
-
Balancing performance and resources:
- set up
IdleTimeout
When you do, make sure it is long enough to complete the request, but not too long to waste resources. - set up
KeepAliveTimeout
When doing so, ensure that it multiplexes connections efficiently to improve performance.
- set up
-
Testing and Monitoring:
- In practice, monitor connection usage and adjust these timeout settings based on performance and resource usage.
By setting these two timeout values appropriately, you can optimize the efficiency of connection usage while avoiding unnecessary resource usage.