gabrielanhaia / php-circuit-breaker
PHP微服务电路断路器。
Requires
- ext-redis: *
- eloquent/enumeration: ^6.0
- mockery/mockery: ^1.4
Requires (Dev)
- phpunit/phpunit: ^9.2
This package is auto-updated.
Last update: 2024-09-17 06:42:56 UTC
README
PHP电路断路器
描述
PHP电路断路器是基于Michael T. Nygard撰写的《发布它!设计和部署可投入生产的软件》(Pragmatic Programmers)一书开发的。在这本书中,Michael推广了电路断路器。
当我们在微服务中工作时,有时会调用这些系统,而这些系统不可用,这最终会导致我们的应用程序出现问题。为了防止我们这边出现任何问题,并确保一个服务不会被多次调用,我们应该使用电路断路器。
您可以在这里找到有关电路断路器的更多信息。
要求
- PHP 7
- Redis
- Redis PHP扩展已启用
- Composer
安装
您可以通过运行以下命令安装PHP电路断路器:# composer require gabrielanhaia/php-circuit-breaker
如何使用它?
我强烈建议您使用服务容器(依赖注入容器)来处理对象及其依赖项,这样您就可以有效地使用它(您不需要在每个地方创建实例)。
- 您可以首先定义设置
$settings = [ 'exceptions_on' => false, // Define if exceptions will be thrown when the circuit is open. 'time_window' => 20, // Time window in which errors accumulate (Are being accounted for in total). 'time_out_open' => 30, // Time window that the circuit will be opened (If opened). 'time_out_half_open' => 20, // Time out that the circuit will be half-open. 'total_failures' => 5 // Number of failures necessary to open the circuit. ];
注意:没有必要定义这些设置(它们是默认值),它们将被自动定义。
- 实例化驱动程序(目前只提供Redis驱动程序)和Redis客户端
$redis = new \Redis; $redis->connect('localhost'); $redisCircuitBreakerDriver = new GabrielAnhaia\PhpCircuitBreaker\Adapter\Redis\RedisCircuitBreaker($redis);
- 实例化PHP电路断路器类
$circuitBreaker = new GabrielAnhaia\PhpCircuitBreaker\CircuitBreaker($redisCircuitBreakerDriver, $settings)
注意:第二个参数是可选的。
- 验证电路是否开启
if ($circuitBreaker->canPass($serviceName) !== true) { return; }
您可以使用任何方式使用canPass函数。当电路处于关闭或半开启状态时,它总是返回true。之后,您应该调用您的服务,并根据响应调用以下方法来更新电路控制变量。
如果成功
$circuitBreaker->succeed($serviceName);
如果失败
$circuitBreaker->failed($serviceName);
使用这三个简单的方法,您可以控制应用程序在执行时间内的流程。
总结
假设您正在使用以下设置
$settings = [ 'exceptions_on' => false, // Define if exceptions will be thrown when the circuit is open. 'time_window' => 20, // Time window in which errors accumulate (Are being accounted for in total). 'time_out_open' => 30, // Time window that the circuit will be opened (If opened). 'time_out_half_open' => 60, // Time out that the circuit will be half-open. 'total_failures' => 5 // Number of failures necessary to open the circuit. ];
您的其中一个服务是支付网关,并且您出于某种原因以每2秒一个间隔尝试调用它。您第一次调用网关时,它返回200(HTTP状态码),然后您使用服务标识符调用“succeed”方法(您可以为每个服务创建一个)。
在第二次、第三次、第四次、第五次和第六次调用时,网关不可用,所以您再次调用“failed”方法。
失败的总数为5,现在当您下次调用“canPass”方法时,它将返回“false”,服务将不再被调用。此时电路已打开,它将保持“打开”状态30秒(time_out_open),然后它将状态更改为“半开启”,此时您可以尝试再次调用服务,如果它失败,它将“打开”30秒。
如果前四次尝试失败而第五次成功会怎样?那么,计数器将被重置。
“time_window”设置是用于什么的?每次故障都会存储在Redis中,并设置一个过期时间。如果第一次故障发生在12:00:10,而“time_window”为30秒,那么,在12:00:40之后,这次故障将不会计入用于开启电路的故障总数。简而言之,要开启电路,必须在Y(time_window)秒的时间间隔内有X(total_failures)次故障。
创建者:Gabriel Anhaia - https://www.linkedin.com/in/gabrielanhaia