pixelfederation/circuit-breaker-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

pixelfederation/circuit-breaker-bundle

Composer 安装命令:

composer require pixelfederation/circuit-breaker-bundle

包简介

An analogous bundle to Java's Hystrix in PHP world.

README 文档

README

This bundle tries to copy the famous java Hystrix library and tries to make the usage of the circuit breaking pattern effortless to the developers.

The developers can just mark any service as circuit broken, using special annotations and this bundle makes all the wiring under the hood automatically.

The current backend implementation is using Ganesha.

Installation

$ composer require pixelfederation/circuit-breaker-bundle

Configuration

Just enable the bundle. There are no configuration options for now.

// in config/bundles.php add this line:
PixelFederation\CircuitBreakerBundle\Bridge\Symfony\PixelFederationCircuitBreakerBundle::class

Usage

To activate circuit breaking on a given service, the service has to implement the PixelFederation\CircuitBreakerBundle\CircuitBrokenService interface.

The class mustn't be marked as final, because a proxy class is derived from it under the hood.

To configure circuit breaking, you can use the class level configuration or method level configuration. The class level configuration is valid for all the circuit-broken methods. It is configured as a class level annotation @CircuitBreakerService. To mark a public method as circuit broken, the @CircuitBreaker annotation or attribute has to be used:

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;
    }
}

or

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;
    }
}

The configuration options for the @CircuitBreakerService are:

  • defaultFallback: a public method of the same class which should be called on an exception occurrence, if no fallback is configured for a circuit-broken method.
  • ignoreExceptions: exception list, which doesn't trigger marking the wrapped service as failing

The method level annotation @CircuitBreaker can override the class level configuration with its own configuration options, which are:

  • fallbackMethod: a public method of the same class which should be called on an exception occurrence
  • ignoreExceptions: exception list, which doesn't trigger marking the wrapped service as failing
use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker;

class Service {
    /**
     * @CircuitBreaker(fallbackMethod="makeSpecialFallbackRequest") 
     */
    public function iShouldBeCircuitBroken(): int
    {
        return 0;
    }
}

or

use PixelFederation\CircuitBreakerBundle\Annotation\CircuitBreaker;

class Service {
    #[CircuitBreaker(fallbackMethod: 'makeSpecialFallbackRequest')]
    public function iShouldBeCircuitBroken(): int
    {
        return 0;
    }
}

The fallback methods have to be public as well.

IMPORTANT: Fallback methods have to have the same method signature as the fallbackable methods, because fallback methods are being called with the same arguments.

IMPORTANT: Doctrine annotations support will be dropped in the future, so it is recommended to use the bundle attributes instead.

NOTICE REGARDING COMPLEX SCENARIOS: It is also possible to define fallback methods for fallback methods in some more complex scenarios. An example of such scenario might be, when there is an API call in the default/fallbackable method. It's fallback method might have a different call to a different API, which means, that such method could use a fallback as well. In that case it can have configured a fallback method which tries to load data from some cache. Such a method might also use a fallback method which might return some default value.

Full example

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
    }
}

Enjoy ;)

pixelfederation/circuit-breaker-bundle 适用场景与选型建议

pixelfederation/circuit-breaker-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 29.18k 次下载、GitHub Stars 达 12, 最近一次更新时间为 2021 年 08 月 13 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 pixelfederation/circuit-breaker-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 pixelfederation/circuit-breaker-bundle 我们能提供哪些服务?
定制开发 / 二次开发

基于 pixelfederation/circuit-breaker-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 29.18k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 12
  • 点击次数: 21
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 12
  • Watchers: 4
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2021-08-13