jbzoo / retry
提供多种回退策略和抖动支持的轻量级PHP重试功能库
README
- 4种重试策略(以及使用您自己的能力)
- 可选的抖动/随机性,以分散重试并最小化冲突
- 等待时间上限
- 自定义重试逻辑或错误处理的回调
备注
- 这是一个分支。您可以在这里找到原始项目。
- 现在代码库非常严格,尽可能多地覆盖了测试。原始作者非常棒,但代码有点糟糕 :) 这太简单了,只花了我一个晚上... ;)
- 我不喜欢在代码中使用“回退”这个词。是的,很有趣,但...我相信“重试”更明显。抱歉 :)
- 使用导入代替全局命名空间中的函数没有问题。不要使用过时的做法。
- 具有默认值的静态变量已弃用并禁用。请参阅以下思考。
- 新方法
setJitterPercent|getJitterPercent
,setJitterMinCap|getJitterMinCap
进行精细调整。 - 我的项目有别名,以与原始项目保持向后兼容。 ;)
安装
composer require jbzoo/retry
默认设置
此库提供合理的默认设置,因此您可以在大多数用例中直接使用。
默认情况下,重试是二次的,基本时间为100毫秒(attempt^2 * 100
),最大重试次数为5次,没有抖动。
快速入门
使用Retry的最简单方法是使用retry
辅助函数
use function JBZoo\Retry\retry; $result = retry(function() { return doSomeWorkThatMightFail(); });
如果成功,则$result
将包含闭包的结果。如果超出最大尝试次数,则内部异常将重新抛出。
当然,如果需要,您可以通过辅助方法提供其他选项。
方法参数是$callback
、$maxAttempts
、$strategy
、$waitCap
、$useJitter
。
Retry类使用
Retry类构造函数参数为$maxAttempts
、$strategy
、$waitCap
、$useJitter
。
use JBZoo\Retry\Retry; $retry = new Retry(10, 'exponential', 10000, true); $result = $retry->run(function() { return doSomeWorkThatMightFail(); });
或者如果您使用依赖注入容器注入Retry类,您可以在之后设置它。请注意,设置器是可链接的。
use JBZoo\Retry\Retry; // Assuming a fresh instance of $retry was handed to you $result = (new Retry()) ->setStrategy('constant') ->setMaxAttempts(10) ->enableJitter() ->run(function() { return doSomeWorkThatMightFail(); });
更改默认设置
重要提示:这是一个分支。所以我只是保留它以保持向后兼容。静态变量已弃用且根本不工作!
这是可怕的实践!明确优于隐式。 ;)
- 示例 #1. 您的项目不同部分可以有不同的设置。
- 示例 #2. 想象一下,如果某个第三方库(在
./vendor
中)使用了它自己的默认设置会发生什么。让我们战斗! - 示例 #3. 这只是一个尝试将变量存储在全局命名空间中的尝试。你看出来了吗?
因此,下一个变量已弃用,并且它们不影响任何内容。
use JBZoo\Retry\Retry; Retry::$defaultMaxAttempts; Retry::$defaultStrategy; Retry::$defaultJitterEnabled;
只需使用依赖注入等方法,不要浪费你的精力。
策略
有四种内置策略可供使用:常数、线性、多项式和指数。
所有策略的基本时间默认为100毫秒。
常数
use JBZoo\Retry\Strategies\ConstantStrategy; $strategy = new ConstantStrategy(500);
此策略将在每次重试循环中暂停500毫秒。
线性
use JBZoo\Retry\Strategies\LinearStrategy; $strategy = new LinearStrategy(200);
此策略将暂停为attempt * baseTime
,提供从200毫秒开始的线性重试。
多项式
use JBZoo\Retry\Strategies\PolynomialStrategy; $strategy = new PolynomialStrategy(100, 3);
此策略将暂停为(attempt^degree) * baseTime
,因此在这种情况下为(attempt^3) * 100
。
如果没有提供,默认程度为2,实际上是二次时间复杂度。
指数型
use JBZoo\Retry\Strategies\ExponentialStrategy; $strategy = new ExponentialStrategy(100);
此策略将睡眠时间为 (2^attempt) * baseTime
。
指定策略
在我们之前的代码示例中,我们指定策略为一个字符串
use JBZoo\Retry\Retry; use function JBZoo\Retry\retry; retry(function() { // ... }, 10, 'constant'); // OR $retry = new Retry(10, 'constant');
这会使用默认值的 ConstantStrategy
,实际上提供了100毫秒的睡眠时间。
您可以通过创建策略实例来修改这些默认值
use JBZoo\Retry\Retry; use JBZoo\Retry\Strategies\LinearStrategy; use function JBZoo\Retry\retry; retry(function() { // ... }, 10, new LinearStrategy(500)); // OR $retry = new Retry(10, new LinearStrategy(500));
您也可以传入一个整数作为策略,将其转换为以毫秒为基时间的 ConstantStrategy
use JBZoo\Retry\Retry; use function JBZoo\Retry\retry; retry(function() { // ... }, 10, 1000); // OR $retry = new Retry(10, 1000);
最后,如果您愿意,可以将闭包作为策略传入。此闭包应接收一个整数 attempt
并返回一个以毫秒为单位的睡眠时间。
use JBZoo\Retry\Retry; use function JBZoo\Retry\retry; retry(function() { // ... }, 10, function($attempt) { return (100 * $attempt) + 5000; }); // OR $retry = new Retry(10); $retry->setStrategy(function($attempt) { return (100 * $attempt) + 5000; });
等待上限
您可能希望使用快速增长的重试时间(如指数型),但同时设置最大等待时间,以便在一段时间后趋于平稳。
此上限可以作为 retry
辅助函数的第四个参数提供,或使用 Retry 类的 setWaitCap()
方法。
抖动
如果您有很多客户端同时开始一个作业并遇到失败,上述任何重试策略都可能导致工人在每次重试时继续碰撞。
解决方案是添加随机性。请参见此处以获取良好的解释
https://aws.amazon.com/ru/blogs/architecture/exponential-backoff-and-jitter
您可以通过将 true
作为 retry
辅助函数的第五个参数传入或使用 Retry 类上的 enableJitter()
方法来启用抖动。
默认情况下,我们使用上述文章中概述的 "FullJitter" 方法,其中使用介于0和所选策略提供的睡眠时间之间的随机数。
但您可以使用 setJitterPercent().
方法更改抖动的最大时间,默认值为100。您还可以使用 setJitterMinCap
设置抖动的最小值(默认为0)。
自定义重试决策者
默认情况下,Retry 遇到异常时会重试,并且尚未达到最大重试次数。
您可能需要提供自己的决策者以用于更复杂的情况。也许您希望根据时间而不是重试次数来重试,或者也许有场景在未遇到异常的情况下您也想要重试。
提供回调或具有 __invoke
方法的类的实例作为决策者。Retry 将传递四个参数:当前尝试次数、最大尝试次数、收到的最后一个结果以及遇到的异常(如果有)。您的决策者需要返回 true 或 false。
use JBZoo\Retry\Retry; $retry = new Retry(); $retry->setDecider(function($attempt, $maxAttempts, $result, $exception = null) { return someCustomLogic(); });
错误处理回调
您可以提供一个自定义的错误处理程序,以便在发生异常时被通知,即使我们尚未达到最大尝试次数。这是一个进行日志记录的有用地方。
use JBZoo\Retry\Retry; $retry = new Retry(); $retry->setErrorHandler(function($exception, $attempt, $maxAttempts) { Log::error("On run {$attempt}/{$maxAttempts} we hit a problem: {$exception->getMessage()}"); });
单元测试和检查代码风格
make update make test-all
许可证
MIT
另请参阅
- CI-Report-Converter - 转换不同的错误报告,以便与流行的 CI 系统实现深度兼容。
- Composer-Diff - 查看
composer update
后更改了哪些包。 - Composer-Graph - 基于 mermaid-js 的 composer.json 的依赖关系图可视化。
- Mermaid-PHP - 使用 mermaid 脚本语言生成图表和流程图。
- Utils - 收集有用的 PHP 函数、迷你类和日常片段。
- Image - 该软件包提供了一种面向对象的方式来尽可能简单地操作图像。
- Data - 扩展了ArrayObject的实现。使用文件作为配置/数组。
- SimpleTypes - 转换任何值和度量 - 货币、重量、汇率、长度、...