The file uploading program will have a certain probability of error, the error rate is about 1% or less, the error message is: . Org. Apache. HTTP NoHttpResponseException, s3-us-west-1.amazonaws.com: 80 failed to respond, looking at is uploaded to the S3 in the process of sending the network error?

Through consulting materials, I found a good article: a NoHttpResponseException problem analysis and solution. This error occurs because the server closes the connection and the client is still using the connection. As a result, the server responds to the RST message and the client receives the RST NoHttpResponseException exception.

To illustrate this scenario, the Keepalive mechanism should be mentioned. Keepalive is an HTTP connection multiplexing mechanism. In the HTTP1.0 era, after three handshakes for each request, only one HTTP request and response packet is transmitted. Then, the connection is closed with four handshakes. The cost of TCP establishing and closing a connection is relatively high, resulting in low channel utilization and high latency of HTTP1.0. To address this problem, the Keepalive mechanism is disabled. After a TCP connection is established, multiple HTTP packets can be sent to the TCP connection. The TCP connection is closed only when the idle time reaches the timeout period. HTTP1.1 Keepalive is enabled by default. This behavior may occur on both the client and the server. For example, if the Keepalive timeout duration of the client is shorter, the client will close the connection first; if the Keepalive timeout duration of the server is shorter, the server will close the connection first.

At first glance it seems fine to close the connection on either side, but there are a few details to watch out for. Server closes the connection, for example, send the FIN bag, the FIN bag sent but not during the period of the client, the client if continue to reuse the TCP connection, sending the HTTP request message, the server will be because during the four waves do not receive a message and send the RST packet to the client, the client receives the RST packet will prompt an exception.

Based on the above theoretical knowledge, Presumably org. Apache. HTTP NoHttpResponseException, S3-us-west-1.amazonaws.com :80 failed to respond The error occurred because the Keepalive time of my application’s HttpClient is longer than that of the S3 server, so an exception may occur when the S3 server closes the connection. Let’s do an experiment.

First write a simple program to observe the Keepalive time on AWS S3 server

String url = "an accessible S3 download address "; CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet request = new HttpGet(url); httpClient.execute(request, response -> { String content = EntityUtils.toString(response.getEntity()); System.out.println(content); return content; }); Thread.sleep(99999);Copy the code

The Wireshark captures HTTP packets and displays the four wave attempts after the packet is captured.

The time between the server sending a FIN packet and the previous request is about 23 seconds, that is, the Keepalive time on the AWS S3 server is about 23 seconds.

Next, we simulate the client sending the request while the server closes the connection to see if we can reproduce the NoHttpResponseException error:

String url = "http://s3-us-west-1.amazonaws.com/sdpcs-prod-awsca/88ea9001-bad0-4b46-86e5-e6bc518c9fdc?Expires=1718171230&response-con tent-type=image/jpeg&response-cache-control=max-age%3D157680000&AWSAccessKeyId=AKIAI7P7PYLVYWVVYTLQ&Signature=iCeE6%2FIH txmOarOc3Q1hUowWqDc%3D"; CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet request = new HttpGet(url); for (int i = 0; i < 100000; i++) { httpClient.execute(request, response -> { String content = EntityUtils.toString(response.getEntity()); System.out.println(content); return content; }); Thread.sleep(23000); }Copy the code

NoHttpResponseException: NoHttpResponseException:

On June 14, 2019 afternoon 2:09:14 org. Apache. HTTP. Impl. Execchain. RetryExec execute information: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to {}->http://s3-us-west-1.amazonaws.com:80: The target server failed to respond on June 14, 2019 2:09:14 org. In The afternoon. The apache HTTP. Impl. Execchain. RetryExec execute information: Retrying request to {}->http://s3-us-west-1.amazonaws.com:80Copy the code

Analyzing packet capture:

You can see that the request number 2400 is 23 seconds after the previous request. Before the server receives the request number 2400, the client receives the FIN request from the server and enters the four-wave process. Then, when the server receives the request no. 2400, it responds to the RST request, causing an error message on the client.

HttpClient provides the ability to close idle connections:

CloseableHttpClient httpClient = HttpClients.custom()
                .evictIdleConnections(5, TimeUnit.SECONDS)
                .build();Copy the code

We set a time lower than S3 Keepalive and execute again without NoHttpResponseException.

In addition to setting the Keepalive time on the client to be shorter than that on the server, it is also possible to retry noHttpresponseExceptions and reduce the number of time_waits.

In this paper, the independent blog: remember a NoHttpResponseException problem screen | wood of Chinese fir blog