gabrielanhaia/laravel-circuit-breaker 问题修复 & 功能扩展

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

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

gabrielanhaia/laravel-circuit-breaker

Composer 安装命令:

composer require gabrielanhaia/laravel-circuit-breaker

包简介

Laravel integration for PHP Circuit Breaker — multiple storage drivers, middleware, Artisan commands, and event system

README 文档

README

CI Latest Stable Version PHP Version Laravel Version License Buy me a coffee

Logo - Laravel Circuit Breaker

A Laravel integration for PHP Circuit Breaker v3 with multiple storage drivers, HTTP middleware, Artisan commands, and full event system integration.

What Is a Circuit Breaker?

When your application calls an external service (payment gateway, email API, etc.), that service can become slow or unresponsive. Without protection, your application keeps sending requests — piling up timeouts, wasting resources, and degrading user experience.

A circuit breaker monitors failures and automatically stops calling a failing service, giving it time to recover. It works like an electrical circuit breaker: when too many failures occur, the circuit "opens" and all requests fail fast without actually hitting the remote service.

stateDiagram-v2
    [*] --> Closed
    Closed --> Open : Failures reach threshold
    Open --> HalfOpen : Timeout expires
    HalfOpen --> Closed : Success threshold met
    HalfOpen --> Open : Any failure
Loading
State Behaviour
Closed Normal operation. Requests pass through. Failures are counted.
Open Requests are blocked immediately (fail fast). No calls reach the service.
Half-Open A limited number of probe requests are allowed through to test recovery.

Requirements

Installation

composer require gabrielanhaia/laravel-circuit-breaker

Publish the configuration file:

php artisan vendor:publish --tag=circuit-breaker-config

Configuration

After publishing, the config lives at config/circuit_breaker.php.

Storage Driver

Choose where circuit state is persisted:

<?php
// config/circuit_breaker.php

return [
    'default_driver' => env('CIRCUIT_BREAKER_DRIVER', 'redis'),

    'drivers' => [
        'redis' => [
            'connection' => env('CIRCUIT_BREAKER_REDIS_CONNECTION', 'default'),
            'prefix'     => 'cb:',
        ],
        'apcu' => [
            'prefix' => 'cb:',
        ],
        'memcached' => [
            'connection' => env('CIRCUIT_BREAKER_MEMCACHED_CONNECTION', 'memcached'),
            'prefix'     => 'cb:',
        ],
        'array' => [],
    ],
    // ...
];
Driver Best for Requirement
redis Distributed / multi-server apps ext-redis (phpredis)
apcu Single-server, high performance ext-apcu
memcached Distributed caching ext-memcached
array Testing and local development none

Note: The Redis driver requires the phpredis PHP extension. Predis is not supported by the underlying storage adapter.

Default Thresholds

<?php
// config/circuit_breaker.php

return [
    // ...
    'defaults' => [
        'failure_threshold'  => 5,     // Number of failures to open the circuit
        'success_threshold'  => 1,     // Successes in half-open to close the circuit
        'time_window'        => 20,    // Seconds in which failures are counted
        'open_timeout'       => 30,    // Seconds the circuit stays open before half-open
        'half_open_timeout'  => 20,    // Seconds the circuit stays half-open
        'exceptions_enabled' => false, // true = throw OpenCircuitException instead of returning false
    ],
    // ...
];

Per-Service Overrides

Different services can have different thresholds. Any key you omit falls back to the value in defaults:

<?php
// config/circuit_breaker.php

return [
    // ...
    'services' => [
        'payment-api' => [
            'failure_threshold' => 3,   // More sensitive — fewer failures to trip
            'open_timeout'      => 60,  // Longer cooldown
        ],
        'email-service' => [
            'failure_threshold' => 10,  // More tolerant
        ],
    ],
];

Usage

Facade

<?php

namespace App\Services;

use GabrielAnhaia\LaravelCircuitBreaker\Facades\CircuitBreaker;
use Illuminate\Support\Facades\Http;

class PaymentService
{
    public function charge(array $data): mixed
    {
        if (!CircuitBreaker::canPass('payment-api')) {
            return $this->fallback();
        }

        try {
            $response = Http::timeout(5)->post('https://api.payment.example/charge', $data);

            CircuitBreaker::recordSuccess('payment-api');

            return $response->json();
        } catch (\Throwable $e) {
            CircuitBreaker::recordFailure('payment-api');

            return $this->fallback();
        }
    }

    private function fallback(): array
    {
        return ['status' => 'queued', 'message' => 'Payment will be retried shortly.'];
    }
}

Dependency Injection

<?php

namespace App\Services;

use GabrielAnhaia\LaravelCircuitBreaker\CircuitBreakerManager;
use Illuminate\Support\Facades\Http;

class PaymentService
{
    public function __construct(
        private readonly CircuitBreakerManager $circuitBreaker,
    ) {}

    public function charge(array $data): mixed
    {
        if (!$this->circuitBreaker->canPass('payment-api')) {
            return $this->fallback();
        }

        try {
            $response = Http::timeout(5)->post('https://api.payment.example/charge', $data);

            $this->circuitBreaker->recordSuccess('payment-api');

            return $response->json();
        } catch (\Throwable $e) {
            $this->circuitBreaker->recordFailure('payment-api');

            return $this->fallback();
        }
    }

    private function fallback(): array
    {
        return ['status' => 'queued'];
    }
}

HTTP Middleware

The circuit-breaker middleware wraps an entire route. It blocks requests when the circuit is open and automatically records successes and failures based on the HTTP status code.

flowchart LR
    A[Incoming Request] --> B{Circuit open?}
    B -- Yes --> C[503 Service Unavailable]
    B -- No --> D[Execute route]
    D --> E{Response 5xx?}
    E -- Yes --> F[recordFailure]
    E -- No --> G[recordSuccess]
    F --> H[Return response]
    G --> H
Loading

Register the middleware on your routes:

<?php
// routes/api.php

use App\Http\Controllers\PaymentController;
use Illuminate\Support\Facades\Route;

Route::middleware('circuit-breaker:payment-api')
    ->post('/payments/charge', [PaymentController::class, 'charge']);

Route::middleware('circuit-breaker:email-service')
    ->post('/notifications/send', [NotificationController::class, 'send']);

When the circuit is open the middleware returns a JSON response:

{
    "message": "Service unavailable."
}

with HTTP status 503 Service Unavailable.

Artisan Commands

# Check the current state of a service's circuit
php artisan circuit-breaker:status payment-api

# Force a state override (useful during deploys or incidents)
php artisan circuit-breaker:force payment-api open
php artisan circuit-breaker:force payment-api closed --ttl=300   # auto-expires in 5 min

# Remove a manual override and return to normal state logic
php artisan circuit-breaker:clear payment-api

Events

All circuit breaker events are dispatched through Laravel's event system, so you can listen to them like any other Laravel event:

<?php
// app/Providers/AppServiceProvider.php

namespace App\Providers;

use GabrielAnhaia\PhpCircuitBreaker\Event\CircuitOpenedEvent;
use GabrielAnhaia\PhpCircuitBreaker\Event\CircuitClosedEvent;
use GabrielAnhaia\PhpCircuitBreaker\Event\FailureRecordedEvent;
use GabrielAnhaia\PhpCircuitBreaker\Event\SuccessRecordedEvent;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Event::listen(CircuitOpenedEvent::class, function (CircuitOpenedEvent $event): void {
            Log::warning("Circuit OPENED for [{$event->getServiceName()}]");
        });

        Event::listen(CircuitClosedEvent::class, function (CircuitClosedEvent $event): void {
            Log::info("Circuit CLOSED for [{$event->getServiceName()}]");
        });
    }
}
Event Fired when
FailureRecordedEvent A failure is recorded
SuccessRecordedEvent A success is recorded
CircuitOpenedEvent The circuit transitions to OPEN
CircuitClosedEvent The circuit transitions to CLOSED
CircuitHalfOpenEvent The circuit transitions to HALF_OPEN

Every event exposes getServiceName(): string and getOccurredAt(): DateTimeImmutable.

Manual Override

Force a circuit state for maintenance windows or during an incident:

<?php

use GabrielAnhaia\LaravelCircuitBreaker\Facades\CircuitBreaker;
use GabrielAnhaia\PhpCircuitBreaker\CircuitState;

// Block all traffic to a service (force OPEN)
CircuitBreaker::forceState('payment-api', CircuitState::OPEN);

// Block for 5 minutes, then automatically return to normal state logic
CircuitBreaker::forceState('payment-api', CircuitState::OPEN, ttl: 300);

// Remove the override
CircuitBreaker::clearOverride('payment-api');

Upgrade from v1

See UPGRADE-2.0.md for step-by-step migration instructions.

Development

composer test        # Run PHPUnit (unit + feature)
composer phpstan     # Static analysis — level max
composer cs-check    # Code style dry-run
composer cs-fix      # Auto-fix code style

Support

If you find this package useful, consider supporting it:

Buy me a coffee

License

MIT. See LICENSE for details.

gabrielanhaia/laravel-circuit-breaker 适用场景与选型建议

gabrielanhaia/laravel-circuit-breaker 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.97k 次下载、GitHub Stars 达 49, 最近一次更新时间为 2020 年 07 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「microservices」 「fault-tolerance」 「circuit-breaker」 「resilience」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

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

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

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

  • 总下载量: 1.97k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 49
  • 点击次数: 9
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 49
  • Watchers: 1
  • Forks: 3
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2020-07-06