承接 syastrebov/circuit-breaker 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

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

syastrebov/circuit-breaker

最新稳定版本:v0.0.9

Composer 安装命令:

composer require syastrebov/circuit-breaker

包简介

Circuit breaker wrapper for microservices and api calls.

README 文档

README

PHP Circuit Breaker implementation for microservices and API calls.

Install

composer require syastrebov/circuit-breaker

Usage

Simple usage:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;

$redis = new \Redis();
$redis->connect('redis');

$circuit = new CircuitBreaker(new RedisProvider($redis));
$response = $circuit->run(
    $name,
    function () {
        // call your api
        return '{"response": "data"}';
    }
);

// {"response": "data"}
echo $response;

Use fallback:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;

$redis = new \Redis();
$redis->connect('redis');

$circuit = new CircuitBreaker(new RedisProvider($redis));
$response = $circuit->run(
    $name,
    // action
    function () {
        throw new \RuntimeException('unable to fetch data');
    },
    // fallback
    function () {
        // call your api
        return '{"response": "cached data"}';
    }
);

// {"response": "cached data"}
echo $response;

Use exception:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;
use CircuitBreaker\Exceptions;

$redis = new \Redis();
$redis->connect('redis');

$circuit = new CircuitBreaker(new RedisProvider($redis));

try {
    $response = $circuit->run(
        $name,
        // action
        function () {
            throw new \RuntimeException('unable to fetch data');
        }
    );
} catch (UnableToProcessException $e) {
    // handle exception
}

Config

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;
use CircuitBreaker\CircuitBreakerConfig;

$redis = new \Redis();
$redis->connect('redis');

$circuit = new CircuitBreaker(new RedisProvider($redis), new CircuitBreakerConfig(
    // Prefix
    prefix: 'api',
    // Number of attempts within run() action
    retries: 5,
    // Number of failed attempts to change state to 'OPEN'
    closedThreshold: 2,
    // Number of succeed attempts to change state to 'CLOSED'
    halfOpenThreshold: 2,
    // Delay between retries within run() action in microseconds
    retryInterval: 1000,
    // TTL of OPEN state in seconds
    openTimeout: 60,
    // If true and no fallback defined returns NULL otherwise throws UnableToProcessException 
    fallbackOrNull: true
));

Supported Drivers

Redis:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;

$redis = new \Redis();
$redis->connect('redis');

$circuit = new CircuitBreaker(new RedisProvider($redis));

Redis cluster:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;

$redis = new \RedisCluster(
    'my cluster',
    [
        'redis-node-1:6379',
        'redis-node-2:6379',
        'redis-node-3:6379',
    ],
    1.5,
    1.5,
    true
);

$circuit = new CircuitBreaker(new RedisProvider($redis));

Predis:

use CircuitBreaker\CircuitBreaker;
use Predis\Client;

$predis = new Client([
    'host' => 'redis',
]);

$predis->connect();

$provider = new PredisProvider($predis);

Predis cluster:

use CircuitBreaker\CircuitBreaker;
use Predis\Client;

$nodes = [
    'redis-node-1:6379',
    'redis-node-2:6379',
    'redis-node-3:6379',
];

$options = [
    // 'redis' (server-side) or 'predis' (client-side)
    'cluster' => 'redis',
];

$predis = new Client($nodes, $options);

$predis->connect();

$provider = new PredisProvider($predis);

Memcached:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\MemcachedProvider;

$memcached = new \Memcached();
$memcached->addServer('memcached', 11211);

$circuit = new CircuitBreaker(new MemcachedProvider($memcached));

MySQL:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\DatabaseProvider;

$table = 'circuit_breaker';

$pdo = new \PDO("mysql:host=mysql;dbname=database", 'user', 'password');
$pdo->prepare("
    CREATE TABLE IF NOT EXISTS $table (
        prefix VARCHAR(255) NOT NULL,
        name VARCHAR(255) NOT NULL,
        state ENUM('closed', 'open', 'half_open'),
        state_timestamp INT,
        half_open_attempts INT,
        failed_attempts INT,
        CONSTRAINT prefix_name_unique UNIQUE (prefix, name)
    );
")->execute();

$provider = new DatabaseProvider($pdo, $table);

PostgreSQL:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\DatabaseProvider;

$table = 'circuit_breaker';

$pdo = new \PDO("pgsql:host=postgres;dbname=database", 'user', 'password');
$pdo->prepare("
    DO $$ 
    BEGIN 
        IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'state_enum') THEN 
            CREATE TYPE state_enum AS ENUM ('closed', 'open', 'half_open'); 
        END IF; 
    END $$;
")->execute();
$pdo->prepare("    
    CREATE TABLE IF NOT EXISTS $table (
        prefix VARCHAR(255) NOT NULL,
        name VARCHAR(255) NOT NULL,
        state state_enum NULL,
        state_timestamp INT,
        half_open_attempts INT,
        failed_attempts INT,
        CONSTRAINT prefix_name_unique UNIQUE (prefix, name)
    );
")->execute();

$provider = new DatabaseProvider($pdo, $table);

SQLite:

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\DatabaseProvider;

$table = 'circuit_breaker';
$databaseFile = __DIR__ . '/database.sqlite';

$pdo = new \PDO("sqlite:$databaseFile");
$pdo->prepare("    
    CREATE TABLE IF NOT EXISTS $table (
        prefix VARCHAR(255) NOT NULL,
        name VARCHAR(255) NOT NULL,
        state TEXT CHECK(state IN ('open', 'half_open', 'closed')),
        state_timestamp INTEGER,
        half_open_attempts INTEGER,
        failed_attempts INTEGER,
        CONSTRAINT prefix_name_unique UNIQUE (prefix, name)
    );
")->execute();

$provider = new DatabaseProvider($pdo, $table);

Logger (optional)

use CircuitBreaker\CircuitBreaker;
use CircuitBreaker\Providers\RedisProvider;
use Monolog\Logger;

$circuit = new CircuitBreaker(
    provider: new MemoryProvider(),
    logger: new Logger('circuit_breaker_channel')
);

Run tests

docker compose up -d
docker compose exec -t php vendor/bin/phpunit

统计信息

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

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-01-26

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固