ejsmont-artur / php-circuit-breaker
PHP 电路断路器组件
Requires
- php: >=5.3.0
This package is not auto-updated.
Last update: 2024-09-14 13:37:01 UTC
README
一个帮助你优雅处理外部服务(通常是远程、第三方服务)故障和超时的组件。
这是一个提供非常容易使用的电路断路器组件的库。它不需要外部依赖,并为APC和Memcached提供默认存储实现,但可以以多种方式扩展。
框架支持
此库不需要任何特定的PHP框架,您只需要PHP 5.3或更高版本。
Symfony 2
如果您使用Symfony 2框架,您应该使用php-circuit-breaker-bundle。这是我创建的一个捆绑包,用于封装php-circuit-breaker并将其与Symfony 2组件和依赖注入集成。
其他框架
如果您使用其他框架并且想使用php-circuit-breaker,请告诉我,我们可以尝试构建一个开源集成,就像为Symfony 2所做的那样。
动机与好处
- 允许应用程序检测故障并适应其行为,而无需人工干预。
- 通过向模块中添加安全功能来提高服务的鲁棒性。
安装
您可以通过下载源代码并使用您的自动加载器来使用它们,或者您可以使用Composer,在这种情况下,您只需要像这样的require
"require": {
"ejsmont-artur/php-circuit-breaker": "*"
},
之后,您应该更新Composer依赖关系,然后就可以继续了。
用例 - 非关键功能
- 您的应用程序有一个非关键功能,如:用户跟踪、统计、推荐等。
- 该可选功能使用远程服务,这会导致您的应用程序出现故障。
- 当“非关键功能”失败时,您希望保持应用程序和核心进程可用。
您的应用程序代码可能如下所示
$factory = new Ejsmont\CircuitBreaker\Factory(); $circuitBreaker = $factory->getSingleApcInstance(30, 300); $userProfile = null; if( $circuitBreaker->isAvailable("UserProfileService") ){ try{ $userProfile = $userProfileService->loadProfileOrWhatever(); $circuitBreaker->reportSuccess("UserProfileService"); }catch( UserProfileServiceConnectionException $e ){ // network failed - report it as failure $circuitBreaker->reportFailure("UserProfileService"); }catch( Exception $e ){ // something went wrong but it is not service's fault, dont report as failure } } if( $userProfile === null ){ // for example, show 'System maintenance, you cant login now.' message // but still let people buy as logged out customers. }
用例 - 支付网关
- Web应用程序依赖于第三方服务(例如支付网关)。
- Web应用程序需要跟踪第三方服务何时不可用。
- 应用程序不能变慢/不可用,它必须告诉用户功能有限或只是隐藏它们。
- 应用程序在渲染结账页面之前使用电路断路器,如果特定的支付网关不可用,则从用户那里隐藏支付选项。
如您所见,这是一个非常强大的概念,可以在运行时选择性地禁用功能,同时仍然允许核心业务流程不间断。
与支付服务通信的后端可能如下所示
$factory = new Ejsmont\CircuitBreaker\Factory(); $circuitBreaker = $factory->getSingleApcInstance(30, 300); try{ // try to process the payment // then tell circuit breaker that it went well $circuitBreaker->reportSuccess("PaymentOptionOne"); }catch( SomePaymentConnectionException $e ){ // If you get network error report it as failure $circuitBreaker->reportFailure("PaymentOptionOne"); }catch( Exception $e ){ // in case of your own error handle it however it makes sense but // dont tell circuit breaker it was 3rd party service failure }
由于您正在记录失败和成功操作,您现在可以在前端使用它们,以隐藏失败的支付选项。
渲染可用支付选项的前端可能如下所示
$factory = new Ejsmont\CircuitBreaker\Factory(); $circuitBreaker = $factory->getSingleApcInstance(30, 300); if ($circuitBreaker->isAvailable("PaymentOptionOne")) { // display the option }
功能
- 通过单个电路断路器实例跟踪多个服务。
- 提供可插拔的后端适配器,默认提供APC和Memcached。
- 可自定义的服务阈值。您可以定义需要多少次失败才能认为服务已关闭。
- 可自定义的重试超时。您不希望永久禁用服务。在提供的时间超时后,电路断路器将允许单个进程尝试
性能影响
电路断路器的开销可以忽略不计。
APC实现大约需要0.0002秒来执行isAvailable()操作,然后报告Success()或reportFailure()。
Memcache适配器在与本地memcached进程通信时的延迟为0.0005秒。
唯一可能影响性能的是网络连接时间。如果您选择使用远程memcached服务器或实现自己的自定义StorageAdapter。
运行测试
- 测试通过PHPUnit运行。假设它是通过PEAR安装的。
- 可以使用phpunit独立运行测试,或通过ant构建目标运行。
- "ci"目标生成代码覆盖率报告,"phpunit"目标则不生成。
您可以通过以下任一方式运行所有测试
ant
ant phpunit
ant ci
您可以通过运行以下命令来运行选定的测试用例
cd tests
phpunit Unit/Ejsmont/CircuitBreaker/Storage/Adapter/DummyAdapterTest.php
详细信息
在文档更新之前,您可以在我的博客上了解更多有关熔断器及其实现的概念:http://artur.ejsmont.org/blog/circuit-breaker
一些实现细节已更改,但核心逻辑仍然相同。
作者
- Artur Esjmont (https://github.com/ejsmont-artur) 通过 http://artur.ejsmont.org