这是HTTP引起的异常,属于偶然发生异常。
异常日志
org.apache.http.NoHttpResponseException: The target server failed to respond
解决方案
服务端方案
客户端可以检测到服务已经过期了,主动关闭。
- 追踪代码我们可以看到是 client 是从 HttpHeader 中读取 Keep-Alive: timeout=xx,如果没有读到就认为永不超时。
- 而 Nginx 配置的第二个参数就是这个,因此只要服务端将 keepalive_timeout 30s;改为 keepalive_timeout 30s 29s;即可,这里少 1s 为了防止网络延时造成的并发问题。
客户端方案
如果服务端不方便修改,那么第二方案是客户端这边修改,比较麻烦。
- 首先保证用最新的
httpClient
。 - 其次有三种方法:
- 对于
jest
这类有定时closeIdleConnection
的,可以将调度时间调整为keep alive
时间的一半以下以保证超时前回收 - 根据
keep Alive
时间,调整validateAfterInactivity 小于
keepAlive Time`,但这种方法依旧不能避免同时关闭。 - 补偿方案,使用
Retry
重新发送尝试一次。HttpClient
默认是打开自动重试的,不要调用disableAutomaticRetries
即可
- 对于
推荐的方案
- 客户端使用短连接,比如换成
UrlConnection
; - 将
HttpClient
连接保活时间调的小于 15s 或者将nginx
的keepalive_timeout
调的大于 30s; - 不用
PoolingHttpClientConnectionManager
; - 出错后重试,
HttpClient
的RetryHandler
; - JDK11已经带了
HttpClinet
,这不吸引人么?