feilong icon indicating copy to clipboard operation
feilong copied to clipboard

httpclient 支持retry功能

Open venusdrogon opened this issue 2 years ago • 5 comments

httpclient 支持retry功能

venusdrogon avatar Jul 07 '22 07:07 venusdrogon

org.apache.http.impl.client.HttpClientBuilder.build() L1128

// Add request retry executor, if not disabled
    if (!automaticRetriesDisabled) {
        HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
        if (retryHandlerCopy == null) {
            retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;
        }
        execChain = new RetryExec(execChain, retryHandlerCopy);
    }

image

关于 org.apache.http.impl.execchain.RetryExec.execute(HttpRoute, HttpRequestWrapper, HttpClientContext, HttpExecutionAware)

image

其中 是否 可重复 请求是否可重复 RequestEntityProxy.isRepeatable(HttpRequest)


    static boolean isRepeatable(final HttpRequest request) {
        if (request instanceof HttpEntityEnclosingRequest) {
            final HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
            if (entity != null) {
                if (isEnhanced(entity)) {
                    final RequestEntityProxy proxy = (RequestEntityProxy) entity;
                    if (!proxy.isConsumed()) {
                        return true;
                    }
                }
                return entity.isRepeatable();
            }
        }
        return true;
    }

put / post /patch 是HttpEntityEnclosingRequest 子类, 其他直接返回true

关于 HttpEntity

post requestBody 是使用的 StringEntity

param 使用的是 UrlEncodedFormEntity 是StringEntity 的子类

然后 判断 entity.isRepeatable()

  • org.apache.http.entity.StringEntity.isRepeatable()
  • org.apache.http.entity.ByteArrayEntity.isRepeatable()
  • org.apache.http.entity.EntityTemplate.isRepeatable()
  • org.apache.http.entity.FileEntity.isRepeatable()
  • org.apache.http.entity.SerializableEntity.isRepeatable()

是true

  • org.apache.http.entity.BasicHttpEntity.isRepeatable()
  • org.apache.http.entity.InputStreamEntity.isRepeatable() 是false

image

默认使用 org.apache.http.impl.client.DefaultHttpRequestRetryHandler 自动重连3次

venusdrogon avatar Jul 10 '22 08:07 venusdrogon

默认


InterruptedIOException.class,
                UnknownHostException.class,
                ConnectException.class,
                SSLException.class

4个不重试

而 SocketTimeoutException 正好属于 InterruptedIOException

image

venusdrogon avatar Jul 10 '22 08:07 venusdrogon

dingtalk 是post 请求

 //---------------------------------------------------------------
    HttpRequest httpRequest = new HttpRequest(BOT_WEBHOOK_URL, POST);

https://blog.csdn.net/shope9/article/details/124047321

默认 不是幂等的请求不重试

venusdrogon avatar Jul 10 '22 08:07 venusdrogon

HttpClient默认是有重试机制的,其重试策略是:

1.只有发生IOExecetion时才会发生重试

2.InterruptedIOException、UnknownHostException、ConnectException、SSLException,发生这4中异常不重试

3.get方法可以重试3次,post方法在socket对应的输出流没有被write并flush成功时可以重试3次。

4.读/写超时不进行重试

5.socket传输中被重置或关闭会进行重试

6.以及一些其他的IOException,暂时分析不出来。

venusdrogon avatar Jul 10 '22 09:07 venusdrogon

StandardHttpRequestRetryHandler

According to RFC-2616 section 9.1.2 the idempotent HTTP methods are: GET, HEAD, PUT, DELETE, OPTIONS, and TRACE

都会去重试

venusdrogon avatar Jul 19 '22 08:07 venusdrogon

image

venusdrogon avatar Sep 16 '22 02:09 venusdrogon