acesseseucondominio / laravel-circuit-breaker
基于laravel-circuit-breaker包(https://github.com/francescomalatesta/laravel-circuit-breaker)实现的Laravel框架5.5的断路器模式。
Requires
- php: >= 7.1
Requires (Dev)
- orchestra/testbench: ^3.5
- phpunit/phpunit: ~7.0
- squizlabs/php_codesniffer: ^2.3
This package is not auto-updated.
Last update: 2024-09-25 18:09:23 UTC
README
Laravel框架5.6的断路器模式实现。
如果您需要为您的Laravel应用程序提供易于使用的断路器模式实现,您就找到了正确的位置。
注意:此包基于laravel circuit breaker包(https://github.com/francescomalatesta/laravel-circuit-breaker),在此存储库中添加了对laravel 5.5及以下版本的兼容性,仅在laravel 5.5中进行测试。
安装
您可以使用Composer为您的项目安装此包。
$ composer require acesseseucondominio/laravel-circuit-breaker
不用担心服务提供者和外观:Laravel可以自动发现包而无需做任何事情!
只需记得使用以下命令发布配置文件:
php artisan vendor:publish
使用方法
您将始终使用一个类(CircuitBreaker
外观或CircuitBreakerManager
类,如果您想将其注入)来使用此包。
以下是方法参考
isAvailable(string $identifier) : bool
如果$identifier
服务当前可用,则返回true
。否则返回false
。
注意:您可以使用任何您想要的作为标识符。我尽量使用MyClass::class
名称。
reportFailure(string $identifier) : void
报告对$identifier
服务的失败尝试。请参阅下面的配置部分,了解如何管理尝试和失败次数。
reportSuccess(string $identifier) : void
报告对$identifier
服务的成功尝试。您可以使用它将服务标记为可用,并从其中删除“失败”状态。
配置
默认值
通过编辑config/circuit_breaker.php
配置文件内容,您可以以更适合您需求的方式调整断路器。
在default
项下有三个值:
<?php return [ 'defaults' => [ 'attempts_threshold' => 3, 'attempts_ttl' => 1, 'failure_ttl' => 5 ], // ... ];
- attempts_threshold:用于指定在声明服务“失败”之前必须尝试的次数 - 默认:3;
- attempts_ttl:用于指定在声明服务“失败”之前必须尝试的时间窗口(以分钟为单位) - 默认:1;
- failure_ttl:一旦服务被标记为“失败”,它将保持此状态几分钟 - 默认:5;
为了更好地理解:默认情况下,1分钟内3次失败尝试将导致服务“失败”5分钟。
服务映射
调整配置文件很酷,但如果我需要为特定服务具有特定的TTL和尝试次数怎么办?没问题:这里有一个“services”选项来帮助。
如您在config/circuit_breaker.php
配置文件中看到的,您还有一个“services”项。您可以在其中指定单个服务的设置。以下是一个示例:
<?php return [ 'defaults' => [ 'attempts_threshold' => 3, 'attempts_ttl' => 1, 'failure_ttl' => 5 ], 'services' => [ 'my_special_service_identifier' => [ 'attempts_threshold' => 2, 'attempts_ttl' => 1, 'failure_ttl' => 10 ] ] ];
然后,当您调用CircuitBreaker::reportFailure('my_special_service_identifier')
时,断路器将识别“特殊”服务并使用特定的配置设置、TTL和尝试次数。
提示:您还可以在service
数组中覆盖单个服务的设置。其他设置将与默认设置合并。
使用示例
假设我们为应用程序集成了支付网关。我们将这个类称为 PaymentsGateway
。
现在,让我们也假设这是一个第三方服务:有时它可能会中断一段时间。然而,我们不希望阻止用户购买东西,所以如果 PaymentsGateway
服务不可用,我们希望将订单重定向到名为 DelayedPaymentsGateway
的备用服务,该服务将简单地将延迟订单“排队”,以便将来处理。
让我们在下面的 BuyArticleOperation
类中模拟这个过程。
<?php class BuyArticleOperation { /** @var PaymentsGateway */ private $paymentsGateway; /** @var DelayedPaymentsGateway */ private $delayedPaymentsGateway; public function process(string $orderId) { // doing stuff with my order and then... try { $this->paymentsGateway->attempt($orderId); } catch (PaymentsGatewayException $e) { // something went wrong, let's switch the payment // to the "delayed" queue system $this->delayedPaymentsGateway->queue($orderId); } } }
太好了!现在我们100%确信我们的支付将会被处理。有时这还不够。
你知道吗,PaymentsGateway
可能需要至少5秒钟来处理一次尝试,而你的应用程序每分钟会接收数百个订单。即使我们知道它第一次尝试就失败了,反复调用 PaymentsGateway
真的有帮助吗?
这就是你如何使用这个断路器来编写你的代码。
<?php use CircuitBreaker; use My\Namespace\PaymentsGateway; use My\Namespace\DelayedPaymentsGateway; class BuyArticleOperation { /** @var PaymentsGateway */ private $paymentsGateway; /** @var DelayedPaymentsGateway */ private $delayedPaymentsGateway; public function process(string $orderId) { if(CircuitBreaker::isAvailable(PaymentsGateway::class)) { try { $this->paymentsGateway->attempt($orderId); } catch (PaymentsGatewayException $e) { // something went wrong, let's switch the payment // to the "delayed" queue system and report that // the default gateway is not working! $this->delayedPaymentsGateway->queue($orderId); CircuitBreaker::reportFailure(PaymentsGateway::class); } // there's nothing we can do here anymore return; } // we already know that the service is disabled, so we // can queue the payment process on the delayed queue // directly, without letting our users wait more $this->delayedPaymentsGateway->queue($orderId); } }
假设我们在10秒钟内处理了100个订单(在不同的进程上)。
- 对于第一个订单,我们要求
PaymentsGateway
处理它,但出了一些问题; - 我们在
DelayedPaymentsGateway
上排队支付,并向CircuitBreaker
报告失败; - 第2和第3个订单也是如此;
- 在处理第三个订单后,
CircuitBreaker
决定在3次尝试(不到1分钟)后,可以宣布PaymentsGateway
“失败”,我们可以直接使用我们的DelayedPaymentsGateway
备用服务一段时间(5分钟); - 剩余的97个订单被排队并成功处理,而没有浪费在明显不会工作的服务上的时间(97 * 5 = 485处理秒);
酷吧? :)
测试
你可以轻松地执行以下测试
$ vendor/bin/phpunit
即将推出
- 指数退避失败TTLs;
- 设置小于1分钟的TTLs;
- 使底层存储实现可定制;
贡献
请参阅CONTRIBUTING 和 CODE_OF_CONDUCT 以获取详细信息。
安全性
如果你发现任何安全问题,请通过电子邮件francescomalatesta@live.it 而不是使用问题跟踪器。
鸣谢
许可
MIT许可(MIT)。有关更多信息,请参阅许可文件。