文档章节

最好的重试是指数后退和抖动

liululee
 liululee
发布于 09/22 21:54
字数 1376
阅读 7
收藏 0

1. 概述

在本教程中,我们将探讨如何使用两种不同的策略改进客户端重试:指数后退和抖动。

2. 重试

在分布式系统中,多个组件之间的网络通信随时可能发生故障。

客户端应用程序通过实现重试来处理这些失败。

设想我们有一个调用远程服务的客户端应用程序—— PingPongService

interface PingPongService {
    String call(String ping) throws PingPongServiceException;
}

如果 PingPongService 返回一个 PingPongServiceException ,则客户端应用程序必须重试。在以下选项当中,我们将考虑实现客户端重试的方法。

3. Resilience4j 重试

在我们的例子中,我们将使用 Resilience4j 库,特别是它的 retry 模块。我们需要将添加 resilience4j-retry 模块到 pom.xml

<dependency>
    <groupid>io.github.resilience4j</groupid>
    <artifactid>resilience4j-retry</artifactid>
</dependency>

关于重试的复习,不要忘记查看我们的 Resilience4j 指南

4. 指数后退

客户端应用程序必须负责地实现重试。当客户在没有等待的情况下重试失败的调用时,他们可能会使系统不堪重负,并导致已经处于困境的服务进一步降级。

指数回退是处理失败网络调用重试的常用策略。简单地说,客户端在连续重试之间等待的时间间隔越来越长:

wait_interval = base * multiplier^n

其中,

  • base 是初始间隔,即等待第一次重试
  • n 是已经发生的故障数量
  • multiplier 是一个任意的乘法器,可以用任何合适的值替换

通过这种方法,我们为系统提供了喘息的空间,以便从间歇性故障或更严重的问题中恢复过来。

我们可以在 Resilience4j 重试中使用指数回退算法,方法是配置它的 IntervalFunction ,该函数接受 initialIntervalmultiplier

重试机制使用 IntervalFunction 作为睡眠函数:

IntervalFunction intervalFn =
  IntervalFunction.ofExponentialBackoff(INITIAL_INTERVAL, MULTIPLIER);

RetryConfig retryConfig = RetryConfig.custom()
  .maxAttempts(MAX_RETRIES)
  .intervalFunction(intervalFn)
  .build();
Retry retry = Retry.of("pingpong", retryConfig);

Function<string, string> pingPongFn = Retry
    .decorateFunction(retry, ping -&gt; service.call(ping));
pingPongFn.apply("Hello");

让我们模拟一个真实的场景,假设我们有几个客户端同时调用 PingPongService

ExecutorService executors = newFixedThreadPool(NUM_CONCURRENT_CLIENTS);
List<callable> tasks = nCopies(NUM_CONCURRENT_CLIENTS, () -&gt; pingPongFn.apply("Hello"));
executors.invokeAll(tasks);

让我们看看 NUM_CONCURRENT_CLIENTS = 4 的远程调用日志:

[thread-1] At 00:37:42.756
[thread-2] At 00:37:42.756
[thread-3] At 00:37:42.756
[thread-4] At 00:37:42.756

[thread-2] At 00:37:43.802
[thread-4] At 00:37:43.802
[thread-1] At 00:37:43.802
[thread-3] At 00:37:43.802

[thread-2] At 00:37:45.803
[thread-1] At 00:37:45.803
[thread-4] At 00:37:45.803
[thread-3] At 00:37:45.803

[thread-2] At 00:37:49.808
[thread-3] At 00:37:49.808
[thread-4] At 00:37:49.808
[thread-1] At 00:37:49.808

我们可以在这里看到一个清晰的模式——客户机等待指数级增长的间隔,但是在每次重试(冲突)时,它们都在同一时间调用远程服务。

img

我们只解决了问题的一部分 - 我们不再重新启动远程服务,**但是,取而代之的是随着时间的推移分散工作量,我们在工作时间间隔更多,空闲时间更长。**此行为类似于惊群问题

5. 介绍抖动

在我们前面的方法中,客户机等待时间逐渐变长,但仍然是同步的。**添加抖动提供了一种方法来中断跨客户机的同步,从而避免冲突。**在这种方法中,我们给等待间隔增加了随机性。

wait_interval = (base * 2^n) +/- (random_interval)

其中,random_interval 被添加(或减去)以打破客户端之间的同步。

我们不会深入研究随机区间的计算机制,但是随机化必须将峰值空间分离到更平滑的客户端调用分布。

我们可以通过配置一个指数随机回退 IntervalFunction,它也接受一个 randomizationFactor,从而在 Resilience4j 重试中使用带有抖动的指数回退:

IntervalFunction intervalFn = 
  IntervalFunction.ofExponentialRandomBackoff(INITIAL_INTERVAL, MULTIPLIER, RANDOMIZATION_FACTOR);

让我们回到我们的真实场景,并查看带抖动的远程调用日志:

[thread-2] At 39:21.297
[thread-4] At 39:21.297
[thread-3] At 39:21.297
[thread-1] At 39:21.297

[thread-2] At 39:21.918
[thread-3] At 39:21.868
[thread-4] At 39:22.011
[thread-1] At 39:22.184

[thread-1] At 39:23.086
[thread-5] At 39:23.939
[thread-3] At 39:24.152
[thread-4] At 39:24.977

[thread-3] At 39:26.861
[thread-1] At 39:28.617
[thread-4] At 39:28.942
[thread-2] At 39:31.039

现在我们有了更好的传播。我们已经消除了冲突和空闲时间,并以几乎恒定的客户端调用率结束,除非出现最初的激增。

img

注意:我们夸大了插图的间隔时间,在实际情况中,我们会有较小的差距。

6. 结论

在本教程中,我们探讨了如何通过使用抖动增加指数回退来改进客户端应用程序重试失败调用的方法。本教程中使用的示例的源代码可以在 GitHub 上找到。

> 原文:https://www.baeldung.com/resilience4j-backoff-jitter > > 作者:Priyank Srivastava > > 译者:Queena

9月福利,关注公众号 ​ 后台回复:004,领取8月翻译集锦! ​ 往期福利回复:001,002, 003即可领取!

img</callable></string,>

© 著作权归作者所有

liululee
粉丝 127
博文 71
码字总数 100192
作品 0
杭州
程序员
私信 提问
《C#并发编程经典实例》学习笔记—2.1 暂停一段时间

问题: 需要让程序(以异步方式)等待一段时间。 解决方案:Task类的静态函数Delay,返回Task对象 在github开源项目,找到Task.cs有关Delay方法的源码 github地址: https://github.com/dot...

repeatedly
2018/08/30
0
0
自旋锁学习系列(3):指数后退技术

上一篇中分析了测试锁的两种实现TASLock和TTASLock,主要对这两种锁的性能进行了分析。对于TTASLock,我们知道比TASLock性能上要好很多,具体分析已经讲过了。我们最后也说了,TTASLock虽然比...

凯奥斯
2013/07/04
388
2
Spring Retry重试机制

在调用第三方接口或者使用mq时,会出现网络抖动,连接超时等网络异常,所以需要重试。为了使处理更加健壮并且不太容易出现故障,后续的尝试操作,有时候会帮助失败的操作最后执行成功。例如,...

aoho
2018/05/09
0
0
unity 关于添加自动导航NavMeshAgent后模型动画的抖动问题

(前提是动画本身没有问题)这个时候如果单帧观察,会发现模型发生奇怪的位移或旋转等问题,但是NavMeshAgent组件的位置没有变化,把它设置为enabled=false; 模型不再抖动。所以发现问题的所...

qq_24378389
2017/03/25
0
0
[译] 用 API 请求制作赏心悦目的 UX

原文地址:Crafting beautiful UX with API requests 原文作者:Ryan Baker 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:MeFelixWang 校对者:sunhaokk 在构建 We...

MeFelixWang
2018/09/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kylin构建Cube过程详解

1 前言 在使用Kylin的时候,最重要的一步就是创建cube的模型定义,即指定度量和维度以及一些附加信息,然后对cube进行build,当然我们也可以根据原始表中的某一个string字段(这个字段的格式...

大数据技术进阶
7分钟前
3
0
Git保存密码

保存密码 $ git config --global credential.helper store 参数 --global 设置全局,如果用 --local 则只设置当前库 要注意保存时是用明文保存的,所以不要在公用电脑使用...

编程老陆
9分钟前
4
0
ofcms 说明文档

一、模板说明 项目概述 java 版CMS系统、基于java技术研发的内容管理系统、功能:栏目模板自定义、内容模型自定义、多个站点管理、在线模板页面编辑等功能、代码完全开源、MIT授权协议。 技术...

kuchawyz
16分钟前
3
0
理解CSS相对定位和固定定位

本文转载于:专业的前端网站➦理解CSS相对定位和固定定位 前面的话   一般地,说起定位元素是指position不为static的元素,包括relative、absolute和fixed。前面已经详细介绍过absolute绝对...

前端老手
26分钟前
3
0
iOS Xcode升级包地址(感谢大神)

下载地址:DeviceSupport

_____1____
40分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部