RxSwift中重试运算符的指数补偿

本文将专门介绍我们称为RxSwiftAutoRetry的新开源库。 它是RxSwift的一个小扩展,可以重试以指数延迟的流。 它不是很复杂,我相信该操作员可以节省时间,并有助于发送网络请求。 在进一步详细介绍该库的确切功能以及如何正确使用它之前,我想向您简要说明为什么我们决定创建它。

前一段时间,当我创建一个用于测试的小项目时,我想尽可能多地利用RxSwift。 该项目将服务用于请求,这些服务也由RxSwift维护。 一切都按预期进行。 但是我在负责请求的部分上工作的时间越长,我就越想知道它在每种情况下是否都能正常工作。 然后我意识到,这会在接收瞬​​态故障时引起潜在的问题。

短期内,短暂故障是由于服务不可用(网络错误或服务器过载)而无法与外部服务进行通信时发生的一种故障。 但是,几秒钟后再次调用服务可能会成功。 为了防止瞬态故障,我们可以使用指数退避算法,该算法在每次重试时都会以指数方式增加延迟时间。

为什么采用指数算法? 想象一下当您由于服务过载而收到瞬态故障时的情况。 当新请求接近该服务时,它们将自动被拒绝。 如果我们不断尝试以固定的时间重试,则可能会成功。 但是,我们也会增加服务的负担。 在这种情况下,服务将保持不可用状态的时间更长,恢复时间也将更长。 但是,如果不是在固定的时间延迟后重试,而是在每次重试时增加它,该怎么办? 例如,第一次失败后,我们将等待1秒,第二次失败后,将等待2秒,第三次失败后,将等待4秒,依此类推。 这可以使我们的服务有足够的休息时间来解决过载问题。

重试运算符已经在RxSwift中实现,但是我认为它与网络请求不兼容,因为:

  • 收到错误事件后立即重新发出所有事件(无延迟)
  • 如果用户提供参数,则重新发射将处于无限循环中,或者将持续指定的重试次数
  • 如果某些实例同时发出,则可能发生数据包冲突。

为了避免数据包冲突,我们的重试操作符版本使用了抖动。 它是一个乘以指数值的随机值。 因此,即使两个用户同时发送网络请求,也不会有任何数据包冲突。

我们提供了三种非常简单的方法将库导入项目。 您可以通过CocoaPods,Carthage和Swift Package Manager来完成。 所有说明均在本文开头提到的GitHub站点上提供。 那么您如何使用它呢? 这很简单。 最简单的方法:

  Observable.retryExponentially() 

实际上,这就是您需要做的所有事情。 当然,如果您想为此方法提供值,则可以编写如下代码:

不用担心,我将解释这些参数负责什么:

  • maxAttemptCount —重复序列的最大次数。 (默认值: 3
  • 抖动 —乘法器,它使延迟时间随机化。 从给定范围内选择随机值。 (默认值: 0.9…1.1
  • 调度程序 —将在其上执行延迟的调度程序。 (默认值: ConcurrentDispatchQueueScheduler(队列:DispatchQueue.global())
  • onRetry —在每次重试延迟后将调用的操作。 这是一个可选参数。 (默认值: nil

这就是我要封装的所有内容。 请随时使用图书馆。 希望对大家有用。