fabiomsouto / phuse
PHP 的无装饰熔断器
Requires
- symfony/polyfill-apcu: ^1.7.0
Requires (Dev)
- phpunit/phpunit: ^7.0
Suggests
- ext-apc: Needed for APC-backed fuses
This package is not auto-updated.
Last update: 2024-09-25 19:01:46 UTC
README
此应用程序实现了 PHP 的熔断器。目前它提供由 APC 支持的不安全熔断器。它受到了 jlouis 在 erlang 中实现的熔断器的极大启发,您可以在 这里 找到。
安装
安装就像运行
$ composer require fabiomsouto/phuse
变更日志
此项目遵循 语义版本控制。
2.0.0
[变更]
- 将覆盖 SplSubject 方法的类方法添加了返回类型,以避免在 php8.1 中出现 E_DEPRECATED 通知,因为方法签名需要相等才能被认为是兼容的。
1.1.0
[新增]
- PHP7 兼容性
[变更]
- 改进 phpdocs
1.0.1
[新增]
- 为附加/分离观察者的单元测试
- 为获取器进行的单元测试
- 这使得我们目前提供的唯一熔断器的单元测试覆盖率达到了 100% :)
[变更]
- 内部,观察者现在存储在一个 SplObjectStorage 对象中。
1.0.0
[新增]
- 熔断器现在也是一个 SplSubject。这样,您可以将 SplObserver 实例附加到它上,并在熔断器熔化或重启时收到通知。
- 添加了 phpunit.xml 规范,因此您可以轻松运行单元测试。
[变更]
- README.md 中的几个链接不起作用,已修复这些问题。
- 向一些单元测试中添加了一些断言,以提供额外的安全性。
0.0.1
[新增]
- 不安全的 APC 熔断器实现:一个异步熔断器,它依赖于 APC 来存储状态。
- FuseBox,用于生成熔断器的工厂
- 基本单元测试
什么是熔断器?
熔断器是一个组件,在熔化后内部短路,类似于现实生活中的熔断器。
它能为我的应用做什么?
熔断器可以帮助您的应用在需要与外部系统通信时更加可靠。假设您的应用 A 与应用 B 通信。如果 B 开始超时或抛出错误,您的应用会如何表现?具体来说,在 PHP 中,如果您有一个 REST 服务,并且它需要同步击中外部端点,外部服务的延迟将导致您的服务具有增加的延迟,锁定工作进程等。熔断器可以位于其中。当您检测到故障时,您会“熔化”熔断器。经过一定次数的熔化后,熔断器“爆炸”,一段时间内将不会接触您的服务,从而打破这个依赖链。然后,您的服务可以更快地失败,或相应地反应(例如,联系备用服务)。
如何使用熔断器(教程)?
很简单。首先实例化一个熔断器
$M = 10; $T = 100; $R = 1000; $fuse = FuseBox::getUnsafeApcInstance("database", $M, $T, $R);
这将设置一个名为 database
的熔断器。 $M
是熔断器可以承受的熔化次数。 $T
是这些熔化可以发生的时间间隔。因此,在这种情况下,如果 10 次熔化在 100ms 内发生,则熔断器爆炸。熔断器爆炸后,它将在 $R
毫秒后重启,在这种情况下为 1000ms。
在您的熔断器设置完成后,您的应用程序可以询问其状态
$M = 10; $T = 100; $R = 1000; $fuse = FuseBox::getUnsafeApcInstance("database", $M, $T, $R); if ($fuse->ok()) { // do whatever }
这是愉快的情况。但现在假设您正在向某个端点进行 POST,并且它出现错误
$M = 10; $T = 100; $R = 1000; $fuse = FuseBox::getUnsafeApcInstance("database", $M, $T, $R); ... try { $result = $curl->post($url, $data); } catch (Exception $e) { $fuse->melt(); }
您正在向保险丝发出信号,表示存在问题。如果保险丝在一定时间内熔断次数过多,它会熄灭,并保持熄灭状态,直到冷却下来。
我该如何监控保险丝呢?
从Fuse接口继承的每个保险丝也是一个SplSubject。因此,您可以为保险丝创建一个SplObserver并将其注册。每当保险丝熔断或重启时,观察者都会收到通知。
class AFuseObserver implements SplObserver { public function update(SplSubject $subject) { $blown = $subject->blown(); echo "This fuse is now "; echo $blown? "blown\n" : "not blown\n"; } } ... $M = 10; $T = 100; $R = 1000; $fuse = FuseBox::getUnsafeApcInstance("database", $M, $T, $R); $observer = new AFuseObserver(); $fuse->attach($observer); // when the fuse melts you will see something in your terminal $fuse->melt(); // outputs "This fuse is now blown" when the threshold is reached ... // after 1000ms... $fuse->ok(); // outputs "This fuse is now not blown" when the restart period ends
请注意,通知观察者可能需要很长时间。因此,请确保更新调用尽可能简洁,并确保您没有在每次保险丝中注册大量观察者,因为通知所有观察者是一个O(n)操作。
性能
这将很快可用。
测试
提供了一些PHPUnit测试。如果您想做出贡献,请确保为您的贡献提供单元测试。