gabrielanhaia/php-circuit-breaker

PHP微服务电路断路器。

1.0.0 2020-06-24 02:07 UTC

This package is auto-updated.

Last update: 2024-09-17 06:42:56 UTC


README

Build Status Code Coverage Licence Package Stars

PHP电路断路器

描述

PHP电路断路器是基于Michael T. Nygard撰写的《发布它!设计和部署可投入生产的软件》(Pragmatic Programmers)一书开发的。在这本书中,Michael推广了电路断路器。

当我们在微服务中工作时,有时会调用这些系统,而这些系统不可用,这最终会导致我们的应用程序出现问题。为了防止我们这边出现任何问题,并确保一个服务不会被多次调用,我们应该使用电路断路器。

您可以在这里找到有关电路断路器的更多信息。

要求

  • PHP 7
  • Redis
  • Redis PHP扩展已启用
  • Composer

安装

您可以通过运行以下命令安装PHP电路断路器:# composer require gabrielanhaia/php-circuit-breaker

如何使用它?

我强烈建议您使用服务容器(依赖注入容器)来处理对象及其依赖项,这样您就可以有效地使用它(您不需要在每个地方创建实例)。

  1. 您可以首先定义设置
$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.
];

注意:没有必要定义这些设置(它们是默认值),它们将被自动定义。

  1. 实例化驱动程序(目前只提供Redis驱动程序)和Redis客户端
$redis = new \Redis;
$redis->connect('localhost');
$redisCircuitBreakerDriver = new GabrielAnhaia\PhpCircuitBreaker\Adapter\Redis\RedisCircuitBreaker($redis);
  1. 实例化PHP电路断路器
$circuitBreaker = new GabrielAnhaia\PhpCircuitBreaker\CircuitBreaker($redisCircuitBreakerDriver, $settings)

注意:第二个参数是可选的。

  1. 验证电路是否开启
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