pixelfederation / circuit-breaker-bundle
PHP世界中类似于Java的Hystrix的类似包。
2.0.1
2024-05-07 07:58 UTC
Requires
- php: >=8.1
- ackintosh/ganesha: ^2.0 || ^3.0
- beberlei/assert: ^3.3
- doctrine/annotations: ^1.12|^2.0
- symfony/cache: ^5.4.24|^6.2
- symfony/framework-bundle: ^5.4.24|^6.2
- symfony/proxy-manager-bridge: ^5.4.21|^6.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.2
- madewithlove/license-checker: ^0.10|^1.0
- nikic/php-parser: ^4.2
- php-parallel-lint/php-parallel-lint: ^1.3
- phpcompatibility/php-compatibility: ^9.1
- phpmd/phpmd: ^2.6
- phpro/grumphp: ^1.5
- phpstan/phpstan: ^1.1
- phpunit/phpunit: ^10.2
- pixelfederation/coding-standards: ^2.1
- roave/security-advisories: dev-master
- squizlabs/php_codesniffer: ^3.4
- symfony/flex: ^2.3
- symfony/monolog-bundle: ^3.7
- symfony/phpunit-bridge: ^5.4.25|^6.2
- vimeo/psalm: ^5.0
README
此包尝试复制著名的Java Hystrix库,并尝试使断路器模式的开发变得简单。
开发者只需将任何服务标记为断路器服务,使用特殊注解,此包将自动处理所有底层连接。
当前的底层实现使用Ganesha。
安装
$ composer require pixelfederation/circuit-breaker-bundle
配置
只需启用此包。目前没有配置选项。
// in config/bundles.php add this line: PixelFederation\CircuitBreakerBundle\Bridge\Symfony\PixelFederationCircuitBreakerBundle::class
使用方法
为了在某个服务上激活断路器,该服务必须实现PixelFederation\CircuitBreakerBundle\CircuitBrokenService
接口。
该类不能被标记为final
,因为底层会从它派生一个代理类。
要配置断路器,您可以使用类级别配置或方法级别配置。类级别配置适用于所有断路器方法。它配置为一个类级别的注解@CircuitBreakerService
。要标记公共方法为断路器,必须使用@CircuitBreaker
注解或属性
use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreakerService; use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker; /** * @CircuitBreakerService( * defaultFallback="makeDefaultFallbackRequest", * ignoreExceptions={BadMethodCallException::class} * ) */ class Service { /** * @CircuitBreaker() */ public function iShouldBeCircuitBroken(): int { return 0; } }
或
use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreakerService; use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker; #[CircuitBreakerService(defaultFallback: 'makeDefaultFallbackRequest', ignoreExceptions: [BadMethodCallException::class])] class Service { #[CircuitBreaker()] public function iShouldBeCircuitBroken(): int { return 0; } }
@CircuitBreakerService
的配置选项包括
- defaultFallback:类中的一个公共方法,在未为断路器方法配置回退时,在异常发生时应调用。
- ignoreExceptions:不触发标记包装服务为失败的异常列表
方法级别注解@CircuitBreaker
可以覆盖类级别配置,并具有自己的配置选项,包括
- fallbackMethod:类中的一个公共方法,在异常发生时应调用
- ignoreExceptions:不触发标记包装服务为失败的异常列表
use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker; class Service { /** * @CircuitBreaker(fallbackMethod="makeSpecialFallbackRequest") */ public function iShouldBeCircuitBroken(): int { return 0; } }
或
use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker; class Service { #[CircuitBreaker(fallbackMethod: 'makeSpecialFallbackRequest')] public function iShouldBeCircuitBroken(): int { return 0; } }
**回退方法也必须是公共的**。
**重要**:回退方法必须与可回退方法的签名相同,因为回退方法将以相同的参数调用。
**重要**:将不支持Doctrine注解,因此建议使用包属性。
**关于复杂场景的注意事项**:在更复杂的场景中,也可以为回退方法定义回退方法。这种场景的一个例子可能是在默认/可回退方法中有一个API调用。它的回退方法可能对不同的API有不同的调用,这意味着这种方法也可以使用回退。在这种情况下,它可以配置一个尝试从某些缓存中加载数据的回退方法。这种方法也可能使用返回某些默认值的回退方法。
完整示例
use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker; use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreakerService; use PixelFederation\CircuitBreakerBundle\CircuitBrokenService; use BadMethodCallException; use InvalidArgumentException; use RuntimeException; /** * The class level annotation activates circuit breaking configuration on methods * marked with the @CircuitBreaker annotation. * In this case, also the default fallback for each circuit broken method is configured * (the 'makeDefaultFallbackRequest' method) * * The ignoreExceptions option sets exceptions, on which occurrence the service won't be marked * as failing, e.g. some app/system level exceptions, which don't need to have to do anything * with http requests under the hood. * * @CircuitBreakerService( * defaultFallback="makeDefaultFallbackRequest", * ignoreExceptions={BadMethodCallException::class} * ) */ class TestService implements CircuitBrokenService { private SomeHttpClient $client; public function __construct(SomeHttpClient $client) { $this->client = $client; } /** * This method is marked to be circuit-broken. It uses the class level configured fallback * and ignores the class level configured exceptions. * * @CircuitBreaker() */ public function makeRequest(): int { return $this->client->makeRequest(); // it is important to set http timeouts here } /** * This method is marked to be circuit-broken. It uses a different fallback, not the one * configured on class level. * * @CircuitBreaker(fallbackMethod="makeSpecialFallbackRequest") */ public function makeRequestWithCustomCircuitBreaker(string $param): int { return $this->client->makeAnotherRequest($param); // it is important to set http timeouts here } public function makeDefaultFallbackRequest(): void { return 1; // ideally there is no call to any external dependency in the fallback method } // notice that this fallback method has the same method signature as the method makeRequestWithCustomCircuitBreaker public function makeSpecialFallbackRequest(string $param): void { return 0; // ideally there is no call to any external dependency in the fallback method } }
祝您玩得开心 ;)