发送标头后立即立即<< <<“ [读取] I / O错误:读取超时”

时间:2018-09-07 17:34:49

标签: http spring-boot networking apache-httpclient-4.x tcp-ip

在Spring Boot应用程序中对外部REST服务的某些调用期间,我们看到超时。当我们直接连接到REST服务时,它们似乎没有发生。 org.apache.http上的调试日志为我们提供了失败请求的一个非常特殊的方面:它在发送标头的中间包含一个入站日志条目'<< "[read] I/O error: Read timed out"'-发送第一个标头的毫秒数。

在发送第一个标头后几毫秒,我们如何看到入站“读取超时”?为何它不立即以超时中断请求/连接,而是等待完整的4500毫秒直到出现异常超时?

这是我们针对失败请求的生产日志,已删除。注意第二和第三行之间的4500ms延迟。我的问题是关于http-outgoing-104 << "[read] I/O error: Read timed out"16:55:08.258的出现,而不是第2行的第一个。

16:55:12.764    Connection released: [id: 104][route: {s}-><<website-redacted>>:443][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
16:55:12.763    http-outgoing-104 << "[read] I/O error: Read timed out"
16:55:08.259    http-outgoing-104 >> "<<POST Body Redacted>>"
16:55:08.259    http-outgoing-104 >> "[\r][\n]"
16:55:08.258    http-outgoing-104: set socket timeout to 4500
16:55:08.258    Executing request POST <<Endpoint Redacted>> HTTP/1.1
16:55:08.258    Target auth state: UNCHALLENGED
16:55:08.258    Proxy auth state: UNCHALLENGED
16:55:08.258    Connection leased: [id: 104][route: {s}-><<website-redacted>>:443][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
....
16:55:08.258    http-outgoing-104 >> "POST <<Endpoint Redacted>> HTTP/1.1[\r][\n]"
16:55:08.258    http-outgoing-104 >> "Accept: text/plain, application/json, application/*+json, */*[\r][\n]"
16:55:08.258    http-outgoing-104 >> Cookie: <<Redacted>>
16:55:08.258    http-outgoing-104 >> "Content-Type: application/json[\r][\n]"
16:55:08.258    http-outgoing-104 >> "Connection: close[\r][\n]"
16:55:08.258    http-outgoing-104 >> "X-B3-SpanId: <<ID>>[\r][\n]"
16:55:08.258    http-outgoing-104 << "[read] I/O error: Read timed out"
16:55:08.258    http-outgoing-104 >> "X-Span-Name: https:<<Endpoint Redacted>>[\r][\n]"
16:55:08.258    http-outgoing-104 >> "X-B3-TraceId: <<ID>>[\r][\n]"
16:55:08.258    http-outgoing-104 >> "X-B3-ParentSpanId: <<ID>>[\r][\n]"
16:55:08.258    http-outgoing-104 >> "Content-Length: 90[\r][\n]"
16:55:08.258    http-outgoing-104 >> "User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_172)[\r][\n]"
16:55:08.258    http-outgoing-104 >> "Cookie: <<Redacted>>"
16:55:08.258    http-outgoing-104 >> "Host: <<Host redacted>>[\r][\n]"
16:55:08.258    http-outgoing-104 >> "Accept-Encoding: gzip,deflate[\r][\n]"
16:55:08.258    http-outgoing-104 >> "X-B3-Sampled: 1[\r][\n

更新1:第二次出现: 在另一个超时的请求中,大致会发生相同的行为,但是即使在发送标头并最终接收到实际超时之前,也会记录超时消息。 注意:该请求实际上是较旧的,在将请求配置为包括“连接:关闭”以避开防火墙后,将连接丢弃在“保持活动”下。

19:28:08.102    http-outgoing-36 << "[read] I/O error: Read timed out"
19:28:08.102    http-outgoing-36: Shutdown connection
19:28:08.102    http-outgoing-36: Close connection
19:28:03.598    http-outgoing-36 >> "Connection: Keep-Alive[\r][\n]"
19:28:03.598    http-outgoing-36 >> "Content-Type: application/json;charset=UTF-8[\r][\n]"
...
19:28:03.598    http-outgoing-36 >> "Accept-Encoding: gzip,deflate[\r][\n]"
...
19:28:03.597    http-outgoing-36 >> Cookie: ....
19:28:03.597    http-outgoing-36 >> Accept-Encoding: gzip,deflate
19:28:03.597    http-outgoing-36 >> User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_172)
19:28:03.596    Connection leased: [id: 36][route: {s}-><< Site redacted >>:443][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
19:28:03.596    http-outgoing-36: set socket timeout to 4500
19:28:03.596    Executing request POST  HTTP/1.1
19:28:03.596    Target auth state: UNCHALLENGED
19:28:03.596    http-outgoing-36 << "[read] I/O error: Read timed out"
19:28:03.594    Connection request: [route: {s}-><< Site redacted >>:443][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
19:28:03.594    Auth cache not set in the context

更新2:添加了HttpClientBuilder配置

RequestConfig.Builder requestBuilder = RequestConfig.custom()
        .setSocketTimeout(socketTimeout)
        .setConnectTimeout(connectTimeout);

CloseableHttpClient httpClient = HttpClientBuilder.create()
        .setDefaultRequestConfig(requestBuilder.build())
        .build();

HttpComponentsClientHttpRequestFactory rf = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(rf);

0 个答案:

没有答案