francescomalatesta/laravel-circuit-breaker
Composer 安装命令:
composer require francescomalatesta/laravel-circuit-breaker
包简介
A circuit breaker pattern implementation for the Laravel framework
README 文档
README
An implementation of the Circuit Breaker pattern for Laravel Framework 5.6.
If you need an easy to use implementation of the circuit breaker pattern for your Laravel application, you're in the right place.
Note: this package is compatible with Laravel 5.6. Other/previous versions are not tested yet.
Install
You can use Composer to install the package for your project.
$ composer require francescomalatesta/laravel-circuit-breaker
Don't worry about service providers and façades: Laravel can auto discover the package without doing nothing!
Just remember to publish the config file with
php artisan vendor:publish
Usage
You will always use a single class (CircuitBreaker façade or CircuitBreakerManager class if you want to inject it) to work with this package.
Here's the methods reference:
isAvailable(string $identifier) : bool
Returns true if the $identifier service is currently available. Returns false otherwise.
Note: you can use whatever you want as identifier. I like to use the MyClass::class name when possible.
reportFailure(string $identifier) : void
Reports a failed attempt for the $identifier service. Take a look at the Configuration section below to know how attempts and failure times are managed.
reportSuccess(string $identifier) : void
Reports a successful attempt for the $identifier service. You can use it to mark a service as available and remove the "failed" status from it.
Configuration
Defaults
By editing the config/circuit_breaker.php config file contents you will able to tweak the circuit breaker in a way that is more suitable for your needs.
You have three values under the default item:
<?php return [ 'defaults' => [ 'attempts_threshold' => 3, 'attempts_ttl' => 1, 'failure_ttl' => 5 ], // ... ];
- attempts_threshold: use it to specify how many attempts you have to make before declaring a service "failed" - default: 3;
- attempts_ttl: use to specify the time (in minutes) window in which the attempts are made before declaring a service "failed" - default: 1;
- failure_ttl: once a service is marked as "failed", it will remain in this status for this number of minutes - default: 5;
For a better understanding: by default, 3 failed attempts in 1 minute will result in a "failed" service for 5 minutes.
Service Map
Tweaking the config file is cool, but what if I need to have specific ttl and attempts count for a specific service? No problem: the services option is here to help.
As you can see in the config/circuit_breaker.php config file, you also have a services item. You can specify settings for a single service here. Here's an example:
<?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 ] ] ];
Then, when you will call CircuitBreaker::reportFailure('my_special_service_identifier'), the circuit breaker will recognize the "special" service and use specific configuration settings, TTLs and attempts count.
Protip: you can also overwrite a single settings for a service in the service array. The others are going to be merged with the defaults.
Usage Example
Let's assume we have a payments gateway integration for our application. We will call this class PaymentsGateway.
Now, let's also assume this is a third party service: sometimes it could be down for a while. However, we don't want to stop our users from buying something, so if the PaymentsGateway service is not available we want to redirect orders to a fallback service named DelayedPaymentsGateway that will simply "queue" delayed orders to process them in the future.
Let's stub this process in the following BuyArticleOperation class.
<?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); } } }
That's great! Now we are 100% sure that our payments are going to be processed. Sometimes that's not enough.
You know, maybe the PaymentsGateway takes at least 5 seconds for a single attempt, and your application receives hundreds of orders every minute. Is it really helpful to repeatedly call the PaymentsGateway even if we "know" it's not working after the first attempt?
Well, this is how you can write your code with this circuit breaker.
<?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); } }
Let's assume we are processing 100 orders (on different processes) in 10 seconds.
- for the first order we ask the
PaymentsGatewayto handle that, but something goes wrong; - we queue the payment on the
DelayedPaymentsGatewayand we report a failure to theCircuitBreaker; - the same goes for the 2nd and 3rd orders;
- after the third order is processed, the
CircuitBreakerdecides that after 3 attempts (and in less than 1 minute) thePaymentsGatewaycan be declared "failed" and we can use directly ourDelayedPaymentsGatewayfallback for a while (5 minutes); - the remaining 97 orders are queued and processed successfully, without wasting time (97 * 5 = 485 processing seconds) on a service we are quite sure that will not work;
Cool, huh? :)
Testing
You can easily execute tests with
$ vendor/bin/phpunit
Coming Soon
- exponential backoff for failure TTLs;
- set TTLs less than 1 minute;
- make underlying store implementation customizable;
Contributing
Please see CONTRIBUTING and CODE_OF_CONDUCT for details.
Security
If you discover any security related issues, please email francescomalatesta@live.it instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
francescomalatesta/laravel-circuit-breaker 适用场景与选型建议
francescomalatesta/laravel-circuit-breaker 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 19.22k 次下载、GitHub Stars 达 29, 最近一次更新时间为 2018 年 04 月 21 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「package」 「laravel」 「circuit breaker」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 francescomalatesta/laravel-circuit-breaker 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 francescomalatesta/laravel-circuit-breaker 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 francescomalatesta/laravel-circuit-breaker 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Circuit Breaker pattern implementation in PHP
Circuit Breaker pattern implementation in Laravel 5.
The Laravel implementation for The Circuit breaker pattern
Simple ASCII output of array data
Alfabank REST API integration
统计信息
- 总下载量: 19.22k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 29
- 点击次数: 14
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2018-04-21