简体   繁体   English

Java Resilience4j 重试策略在 2 次重试后变为无限

[英]Java resilience4j Retry policy goes infinite after 2 retries

I am using the resilience4j Retry policy to call the HttpGet request and for testing purposes,我正在使用resilience4j 4j 重试策略来调用HttpGet请求并用于测试目的,
I have set retryOnResult to retry when HttpGet request returns 200 status code.我已将retryOnResult设置为在HttpGet请求返回200状态码时重试。
It successfully retries when maxAttempts is set to 2 .maxAttempts设置为2时,它会成功重试。

For maxAttempts > 2 application goes in infinite state.对于maxAttempts > 2应用程序进入无限 state。

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: 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>

Thats not true.这不是真的。 If the number of attempts is greater than maxAttempts, the last result is returned to the client.如果尝试次数大于 maxAttempts,则将最后一个结果返回给客户端。 It's not an infinite loop.这不是一个无限循环。

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);

    }

Results in结果是

Retrying
Retrying
Hello World

The third attempt also "failed", but the result is returned to the client.第三次尝试也“失败”,但结果返回给客户端。

Finally found the root cause.终于找到了根本原因。 Issue is not with the resiliency4j.问题不在于resilency4j。 But in above scenario same HttpGet request is called multiple times in retry scenario.但在上述场景中,在重试场景中多次调用相同的 HttpGet 请求。 And by default httpclient creates a pool with size of 2 .默认情况下httpclient 创建一个大小为 2 的池 So after 2 is used, it waits indefinitely trying to get the third connection from the pool.所以在使用 2 之后,它会无限期地等待尝试从池中获取第三个连接。

Final Working Code:最终工作代码:

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();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM