stechstudio/backoff

PHP 库,提供多种回退策略和抖动支持的重试功能

1.4 2024-08-29 21:43 UTC

This package is auto-updated.

Last update: 2024-08-29 21:43:46 UTC


README

Latest Version on Packagist Tests Software License Total Downloads

轻松使用重试功能封装您的代码。此库提供

  1. 4 种回退策略(以及使用您自己的能力)
  2. 可选的抖动/随机性以分散重试并最小化碰撞
  3. 等待时间上限
  4. 用于自定义重试逻辑或错误处理的回调

安装

composer require stechstudio/backoff

默认值

此库提供合理的默认值,因此您可以在大多数用例中直接使用。

默认情况下,回退是二次的,基础时间为 100 毫秒(attempt^2 * 100),最大重试次数为 5,没有抖动。

快速入门

使用 Backoff 的最简单方法是使用全局 backoff 辅助函数

$result = backoff(function() {
    return doSomeWorkThatMightFail();
});

如果成功,$result 将包含闭包的结果。如果超过最大尝试次数,则内部异常将被重新抛出。

当然,如果需要,您可以通过辅助方法提供其他选项。

方法参数是 $callback$maxAttempts$strategy$waitCap$useJitter

Backoff 类使用

Backoff 类构造函数参数是 $maxAttempts$strategy$waitCap$useJitter

$backoff = new Backoff(10, 'exponential', 10000, true);
$result = $backoff->run(function() {
    return doSomeWorkThatMightFail();
});

如果您通过依赖注入容器注入 Backoff 类,则可以在之后设置它。请注意,设置器是可链接的。

// Assuming a fresh instance of $backoff was handed to you
$result = $backoff
    ->setStrategy('constant')
    ->setMaxAttempts(10)
    ->enableJitter()
    ->run(function() {
        return doSomeWorkThatMightFail();
    });

更改默认值

如果您想使用不同的默认值,可以通过静态类属性进行修改

Backoff::$defaultMaxAttempts = 10;
Backoff::$defaultStrategy = 'exponential';
Backoff::$defaultJitterEnabled = true;

例如,您可以在应用程序引导过程中进行此操作。这些默认值将在您创建 Backoff 类实例或使用 backoff() 辅助函数时使用。

策略

有四个内置策略可供使用:常数、线性、多项式和指数。

所有策略的默认基础时间都是 100 毫秒。

常数

$strategy = new ConstantStrategy(500);

此策略将在每次重试循环中暂停 500 毫秒。

线性

$strategy = new LinearStrategy(200);

此策略将在 attempt * baseTime 暂停,提供从 200 毫秒开始的线性回退。

多项式

$strategy = new PolynomialStrategy(100, 3);

此策略将在 (attempt^degree) * baseTime 暂停,因此在这种情况下 (attempt^3) * 100

如果没有提供度数,则默认值为 2,实际上是二次时间。

指数

$strategy = new ExponentialStrategy(100);

此策略将在 (2^attempt) * baseTime 暂停。

指定策略

在我们之前的代码示例中,我们将策略指定为字符串

backoff(function() {
    ...
}, 10, 'constant');

// OR

$backoff = new Backoff(10, 'constant');

这将使用具有默认值的 ConstantStrategy,实际上为您提供 100 毫秒的暂停时间。

您可以自己创建策略实例以修改这些默认值

backoff(function() {
    ...
}, 10, new LinearStrategy(500));

// OR

$backoff = new Backoff(10, new LinearStrategy(500));

您还可以将整数作为策略传递,它将转换为以毫秒为单位的基准时间的 ConstantStrategy

backoff(function() {
    ...
}, 10, 1000);

// OR

$backoff = new Backoff(10, 1000);

最后,如果您愿意,可以将闭包作为策略传递。此闭包应接收整数 attempt 并返回以毫秒为单位的暂停时间。

backoff(function() {
    ...
}, 10, function($attempt) {
    return (100 * $attempt) + 5000;
});

// OR

$backoff = new Backoff(10);
$backoff->setStrategy(function($attempt) {
    return (100 * $attempt) + 5000;
});

等待时间上限

如果您想使用快速增长的回退时间(如指数),但随后也设置最大等待时间,以便过一段时间后水平化。

此上限可以作为 backoff 辅助函数的第四个参数提供,或使用 Backoff 类上的 setWaitCap() 方法。

抖动

如果您有很多客户端同时开始一个作业并遇到故障,上述任何回退策略都可能导致工人在每次重试时继续发生碰撞。

解决这个问题可以通过添加随机性来实现。请参见这里以获得良好的解释

https://www.awsarchitectureblog.com/2015/03/backoff.html

您可以通过将true作为第五个参数传递给backoff辅助函数,或者使用Backoff类的enableJitter()方法来启用抖动。

我们使用上述文章中概述的“FullJitter”方法,该方法使用介于0和您所选策略提供的睡眠时间之间的随机数。

自定义重试决策器

默认情况下,如果遇到异常且尚未达到最大重试次数,Backoff将进行重试。

您可能需要为更高级的使用场景提供自己的重试决策器。也许您想根据时间而不是重试次数来重试,或者可能存在即使在未遇到异常的情况下也想重试的场景。

将决策器作为回调提供,或者提供一个具有__invoke方法的类的实例。Backoff将提供四个参数:当前尝试次数、最大尝试次数、收到的最后一个结果以及如果遇到异常则提供的异常。您的决策器需要返回true或false。

$backoff->setDecider(function($attempt, $maxAttempts, $result, $exception = null) {
    return someCustomLogic();
});

错误处理回调

您可以提供自定义错误处理程序以在发生异常时通知,即使我们尚未达到最大尝试次数。例如,这是一个进行日志记录的有用位置。

$backoff->setErrorHandler(function($exception, $attempt, $maxAttempts) {
    Log::error("On run $attempt we hit a problem: " . $exception->getMessage());
});