美文网首页
网络重试中的 指数退避抖动 算法 Exponential Bac

网络重试中的 指数退避抖动 算法 Exponential Bac

作者: 专职跑龙套 | 来源:发表于2018-11-29 16:31 被阅读147次

    最近项目中用到了很多 RPC 调用,其中定义了一个如下的重试策略:

    public static final RetryStrategy<Object> DEFAULT_RETRY_STRATEGY =
            new ExponentialBackoffAndJitterBuilder()
                    .retryOn(Calls.getCommonRecoverableThrowables())
                    .retryOn(RetryableSBAAGTSvcException.class)
                    .withInitialIntervalMillis(RETRY_INITIAL_INTERVAL_MILLIS)
                    .withMaxAttempts(RETRY_MAX_ATTEMPTS)
                    .build();
    

    关于 指数退避抖动 算法 Exponential Backoff And Jitter,参考如下两篇文章:

    指数退避的原理是对于连续错误响应,重试等待间隔越来越长。
    您应该实施最长延迟间隔最大重试次数。最长延迟间隔和最大重试次数不一定是固定值,并且应当根据正在执行的操作和其他本地因素(例如网络延迟)进行设置。

    大多数指数退避算法会利用抖动(随机延迟)来防止连续的冲突。
    由于在这些情况下您并未尝试避免此类冲突,因此无需使用此随机数字。但是,如果使用并发客户端,抖动可帮助您更快地成功执行请求。

    以下代码演示如何在 Java 中实施此增量延迟。

    public class RetryDemo {
    
        // 最长延迟间隔,单位是毫秒
        private static int MAX_WAIT_INTERVAL = 100000;
        // 最大重试次数
        private static int MAX_RETRIES = 5;
    
        public enum Results {
            SUCCESS,
            NOT_READY,
            THROTTLED,
            SERVER_ERROR
        }
    
        public static void main(String[] args) {
            doOperationAndWaitForResult();
        }
    
        // 指数退避 算法
        public static void doOperationAndWaitForResult() {
    
            try {
                int retries = 0;
                boolean retry = false;
    
                do {
                    long waitTime = Math.min(getWaitTimeExp(retries), MAX_WAIT_INTERVAL);
    
                    System.out.print("等待时间:" + waitTime + " ms \n");
    
                    // Wait for the result.
                    Thread.sleep(waitTime);
    
                    // Get the result of the asynchronous operation.
                    Results result = getAsyncOperationResult();
    
                    if (Results.SUCCESS == result) {
                        retry = false;
                    } else if (Results.NOT_READY == result) {
                        retry = true;
                    } else if (Results.THROTTLED == result) {
                        retry = true;
                    } else if (Results.SERVER_ERROR == result) {
                        retry = true;
                    }
                    else {
                        retry = false;
                    }
    
                } while (retry && (retries++ < MAX_RETRIES));
            }
            catch (Exception ex) {
            }
        }
    
        // 假设每次都返回 SERVER_ERROR
        public static Results getAsyncOperationResult() {
            return Results.SERVER_ERROR;
        }
    
        // 根据重试的次数,返回 2 的指数的等待时间,单位是毫秒
        public static long getWaitTimeExp(int retryCount) {
    
            long waitTime = ((long) Math.pow(2, retryCount) * 100L);
    
            return waitTime;
        }
    
    }
    

    输出如下:

    等待时间:100 ms 
    等待时间:200 ms 
    等待时间:400 ms 
    等待时间:800 ms 
    等待时间:1600 ms 
    等待时间:3200 ms 
    

    相关文章

      网友评论

          本文标题:网络重试中的 指数退避抖动 算法 Exponential Bac

          本文链接:https://www.haomeiwen.com/subject/zhyfcqtx.html