Java resilience4j Политика повторных попыток становится бесконечной после 2 попыток - PullRequest
0 голосов
/ 18 октября 2019

Я использую политику resilience4j Retry для вызова запроса HttpGet и в целях тестирования,
Я установил retryOnResult, чтобы повторить, когда запрос HttpGet возвращает 200 код состояния.
Успешно повторяется, когда maxAttempts установлен на 2.

Для maxAttempts > 2 приложение переходит в бесконечное состояние.

public class App {
    public static void main(String[] args) {
        HttpClient client = HttpClients.createDefault();
        HttpRequest request = new HttpGet("https://jsonplaceholder.typicode.com/todos/1");
        HttpResponse response;
        try {
            RetryConfig retryConfig = RetryConfig.<HttpResponse>custom().waitDuration(Duration.ofSeconds(2))
                    .maxAttempts(3).retryOnResult(s -> {
                        return s.getStatusLine().getStatusCode() == 200;
                    }).build();
            RetryRegistry registry = RetryRegistry.of(retryConfig);
            Retry retry = registry.retry("Http client");
            retry.getEventPublisher().onRetry(e -> {
                System.out.println("Retrying");
            });

            CheckedFunction0<HttpResponse> retryableSupplier = Retry.decorateCheckedSupplier(retry,
                    () -> client.execute((HttpUriRequest) request));
            response = Try.of(retryableSupplier).get();
            HttpEntity entity = response.getEntity();
            System.out.println(EntityUtils.toString(entity));
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

pom.xml:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.3</version>
    </dependency>
    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-circuitbreaker</artifactId>
        <version>1.1.0</version>
    </dependency>

    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-retry</artifactId>
        <version>1.1.0</version>
    </dependency>
</dependencies>

Ответы [ 2 ]

0 голосов
/ 24 октября 2019

Наконец-то найдена основная причина. Проблема не в устойчивости4j. Но в приведенном выше сценарии один и тот же запрос HttpGet вызывается несколько раз при повторном сценарии. И по умолчанию httpclient создает пул размером 2 . Поэтому после использования 2 он бесконечно ждет попытки получить третье соединение из пула.

Окончательный рабочий код:

public class App {
    public static int retryCounter = 0; 
    public static void main(String[] args) {

        int maxAttempts = 4;
        HttpClient client = HttpClients.createDefault();
        HttpRequest request = new HttpGet("https://jsonplaceholder.typicode.com/todos/1");
        HttpResponse response;
        try {

            RetryConfig retryConfig = RetryConfig.<HttpResponse>custom().waitDuration(Duration.ofSeconds(1))
                    .maxAttempts(maxAttempts).retryOnResult(s -> {
                        try {
                            if (s.getStatusLine().getStatusCode() == 200) {

                                if (retryCounter < maxAttempts -1) {
                                    s.getEntity().getContent().close();
                                }
                                return true;
                            } else {
                                return false;
                            }
                        } catch (UnsupportedOperationException e1) {
                            return true;
                        } catch (IOException e1) {
                            // TODO Auto-generated catch block
                            return true;
                        }

                    }).build();
            RetryRegistry registry = RetryRegistry.of(retryConfig);
            Retry retry = registry.retry("Http client");
            retry.getEventPublisher().onRetry(e -> {
                retryCounter ++;
                System.out.println("Retrying" + e.getNumberOfRetryAttempts());

            });

            CheckedFunction0<HttpResponse> retryableSupplier = Retry.decorateCheckedSupplier(retry, () -> {

                HttpResponse res = client.execute((HttpUriRequest) request);
                return res;
            });
            response = (CloseableHttpResponse) Try.of(retryableSupplier).get();
            HttpEntity entity = response.getEntity();
            System.out.println(EntityUtils.toString(entity));
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block`enter code here`
            e.printStackTrace();
        }
    }
0 голосов
/ 18 октября 2019

Это не правда. Если количество попыток больше, чем maxAttempts, последний результат возвращается клиенту. Это не бесконечный цикл.

public static void main(String[] args) {
        String response;
            RetryConfig retryConfig = RetryConfig.<String>custom().waitDuration(Duration.ofMillis(100))
                    .maxAttempts(3).retryOnResult(s -> {
                        return s.contains("Hello");
                    }).build();
            RetryRegistry registry = RetryRegistry.of(retryConfig);
            Retry retry = registry.retry("Http client");
            retry.getEventPublisher().onRetry(e -> {
                System.out.println("Retrying");
            });

            CheckedFunction0<String> retryableSupplier = Retry.decorateCheckedSupplier(retry,
                    () -> "Hello World");
            response = Try.of(retryableSupplier).get();
            System.out.println(response);

    }

Результат

Retrying
Retrying
Hello World

Третья попытка также "не удалась", но результат возвращается клиенту.

...