【线上】加上重试机制(使用guava-retrying)

遇到的需要重试场景:

  • Druid.IO集群中会遇到边界情况

druid集群中有running task, 对于 running task 会有对应的middlemanager进程去运行. druid提供了对应的查看task状态的接口 和 查看进程信息的接口。

会在边界情况出现 查询得到一个task 是 running的,但是去调用获取进程信息的接口调不通的情况

  • druid集群瞬间的pending task情况
    约1-2秒左右,出现大量pending task, 不过随后就变成了 running 状态的

guava retryer的简单使用

import com.github.rholder.retry.*;
import com.google.common.base.Predicates;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

class RsDto{
    public List<Integer> li;

    public RsDto() {
    }

    public RsDto(List<Integer> li) {
        this.li = li;
    }

    @Override
    public String toString() {
        return "RsDto{" +
                "li=" + li +
                '}';
    }
}

/**
 * @Author mubi
 * @Date 2019/3/26 11:21 PM
 */
public class Main {

    private static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss,SSS");

    private static int cnt = 0;

    RsDto test(){
        cnt ++;
        try{
            System.out.println("cnt:" + cnt + ": " + df.format(new Date()));
//            int a = 1 / 0;
        }catch (Exception e){
            e.printStackTrace();
//            throw e;
        }
//        return new Random().nextBoolean();
        if(cnt < 2){
            return null;
        }
        return new RsDto(Arrays.asList(1,2,3));
    }

    public static void main(String[] args){
        Main main = new Main();
        Callable<RsDto> sendTask = () -> main.test();
        Retryer<RsDto> retryer = RetryerBuilder.<RsDto>newBuilder()
                // 抛出Exception 重试
                .retryIfException()
                // return null 重试
                .retryIfResult(Predicates.isNull())
                .withWaitStrategy(WaitStrategies.incrementingWait(1, TimeUnit.SECONDS,2,TimeUnit.SECONDS))
                .withStopStrategy(StopStrategies.stopAfterAttempt(4))
//                .withAttemptTimeLimiter(AttemptTimeLimiters.>fixedTimeLimit(3,TimeUnit.SECONDS))
                .withRetryListener(new RetryListener() {
                    @Override
                    public <RsDto> void onRetry(Attempt<RsDto> attempt) {
                        // 第几次重试,(注意:第一次重试其实是第一次调用)
                        RsDto result = null;
                        System.out.print("[retry]time=" + attempt.getAttemptNumber());
                        if (attempt.hasException()){
                            attempt.getExceptionCause().printStackTrace();
                        }
                        try {
                            result = (RsDto) attempt.get();
                            System.out.println(",rude get=" + result);
                        } catch (ExecutionException e) {
                            System.err.println("this attempt produce exception." + e.getCause().toString());
                        }
                    }
                })
                .build();
        RsDto rs = null;
        try {
            rs = retryer.call(sendTask);
        } catch (ExecutionException e){
//            e.printStackTrace();
            System.out.println("ExecutionException: " + rs);
        } catch (RetryException e1) {
//            e1.printStackTrace();
            System.out.println("RetryException: " + rs);
        }
        System.out.println("main end rs:" + rs);
    }

}

你可能感兴趣的:(Java,项目经验总结)