Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timeout between request retries Apache HttpClient

Could somebody share how to configure modern HttpClient 4.5.3 to retry failed requests and wait for some time before each retry?

So far it looks like I got it correctly that .setRetryHandler(new DefaultHttpRequestRetryHandler(X, false)) will allow to retry requests X times.

But I cannot understand how to configure backoff: .setConnectionBackoffStrategy() / .setBackoffManager() according to JavaDocs regulate something else, not timeout between retries.

like image 342
snowindy Avatar asked Jan 31 '18 11:01

snowindy


3 Answers

About the dynamic delay, I want to suggest this:

CloseableHttpClient client = HttpClientBuilder.create()
    .setRetryHandler(new HttpRequestRetryHandler() {
        @Override
        public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
            return executionCount <= maxRetries ;
        }
    })
    .setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
        int waitPeriod = 100;
        @Override
        public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
            waitPeriod *= 2;
            return executionCount <= maxRetries &&
               response.getStatusLine().getStatusCode() >= 500; //important!
        }

        @Override
        public long getRetryInterval() {
            return waitPeriod;
        }
    })
    .build();

Appendix: Please note, that ServiceUnavailableRetryStrategy.retryRequest will NOT be called, if there was an IO error like timeout, port not open or connection closed. In such cases, only HttpRequestRetryHandler.retryRequest will be called, and the retry will happen either immediately or after a fixed delay (I could not finally clarify this). So oleg's answer is actually the right one. There is no way to do it with support of HttpClient 4.5.

(I would actually like to call this a design bug, as delayed retries after an IO error are vitally important in a modern microservice environment.)

like image 102
user2081279 Avatar answered Oct 09 '22 08:10

user2081279


BackoffManager / ConnectionBackoffStrategy combo can be used to dynamically increase or decrease max connection per route limits based on rate of I/O errors and 503 responses. They have no influence on request execution and cannot be used to control request re-execution

This is the best one can do with HC 4.x APIs

CloseableHttpClient client = HttpClientBuilder.create()
        .setRetryHandler(new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                return executionCount <= maxRetries &&
                        exception instanceof SocketException;
            }
        })
        .setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
            @Override
            public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {
                return executionCount <= maxRetries &&
                        response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
            }

            @Override
            public long getRetryInterval() {
                return 100;
            }
        })
        .build();

Please note there is presently no elegant way of enforcing a delay between request execution attempts in case of an I/O error or dynamically adjusting the retry interval based on request route.

like image 8
ok2c Avatar answered Oct 09 '22 07:10

ok2c


You can use lambda

client.setRetryHandler((e, execCount, httpContext) -> {
                if (execCount > tries) {
                    return false;
                } else {
                    try {
                        Thread.sleep(recalMillis);
                    } catch (InterruptedException ex) {
                        //ignore
                    }
                    return true;
                }

Notice that handler works only for IOExceptions types

like image 1
Artem Demyansky Avatar answered Oct 09 '22 07:10

Artem Demyansky