PHP code example of tourze / symfony-circuit-breaker-bundle

1. Go to this page and download the library: Download tourze/symfony-circuit-breaker-bundle library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

tourze / symfony-circuit-breaker-bundle example snippets


// config/bundles.php
return [
    // ...
    Tourze\Symfony\CircuitBreaker\CircuitBreakerBundle::class => ['all' => true],
];



namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Tourze\Symfony\CircuitBreaker\Attribute\CircuitBreaker;

class ApiController extends AbstractController
{
    #[Route('/api/users', name: 'api_users')]
    #[CircuitBreaker(service: 'api.users', fallbackMethod: 'getUsersFallback')]
    public function getUsers(): Response
    {
        // 可能会失败的操作...
        // 例如:调用外部API
        
        return $this->json([
            'users' => [/* ... */],
        ]);
    }
    
    public function getUsersFallback(): Response
    {
        // 降级处理,当熔断器打开时会调用此方法
        return $this->json([
            'users' => [], 
            'message' => '服务暂时不可用,请稍后再试'
        ], 503);
    }
}



namespace App\Service;

use Tourze\Symfony\CircuitBreaker\Service\CircuitBreakerService;

class ExternalApiService
{
    private CircuitBreakerService $circuitBreaker;
    
    public function __construct(CircuitBreakerService $circuitBreaker)
    {
        $this->circuitBreaker = $circuitBreaker;
    }
    
    public function callExternalApi(): array
    {
        return $this->circuitBreaker->execute(
            'external.api',  // 服务标识
            function() {
                // 实际的API调用代码
                $result = /* ... */;
                
                return $result;
            },
            function() {
                // 降级处理,当熔断器打开时执行
                return [
                    'error' => '服务暂时不可用',
                    'fallback_data' => true,
                ];
            }
        );
    }
}



namespace App\Service;

use Symfony\Contracts\HttpClient\HttpClientInterface;

class ApiClient
{
    private HttpClientInterface $httpClient;
    
    public function __construct(HttpClientInterface $circuitBreakerHttpClient)
    {
        // 自动注入 circuit_breaker.http_client 服务
        $this->httpClient = $circuitBreakerHttpClient;
    }
    
    public function fetchData(): array
    {
        try {
            $response = $this->httpClient->request('GET', 'https://api.example.com/data');
            
            return $response->toArray();
        } catch (\Throwable $e) {
            // 处理异常...
            return [];
        }
    }
}

// 在服务容器中获取
$client = $container->get('circuit_breaker.http_client');

// 或在控制器中
$client = $this->get('circuit_breaker.http_client');

use Tourze\Symfony\CircuitBreaker\Service\CircuitBreakerService;

class YourService
{
    private CircuitBreakerService $circuitBreaker;
    
    public function __construct(CircuitBreakerService $circuitBreaker)
    {
        $this->circuitBreaker = $circuitBreaker;
    }
    
    public function someMethod()
    {
        // 检查服务是否可用
        if (!$this->circuitBreaker->isAvailable('your.service')) {
            // 熔断器打开,执行降级逻辑
            return $this->fallback();
        }
        
        try {
            // 执行可能失败的操作
            $result = $this->doSomething();
            
            // 标记成功
            $this->circuitBreaker->markSuccess('your.service');
            
            return $result;
        } catch (\Throwable $e) {
            // 标记失败
            $this->circuitBreaker->markFailure('your.service');
            
            // 重新抛出或处理异常
            throw $e;
        }
    }
}

// config/services.yaml
services:
    App\Service\HttpClientFallbackFactory:
        arguments: []
        
    circuit_breaker.http_client:
        class: Tourze\Symfony\CircuitBreaker\Service\CircuitBreakerHttpClient
        arguments:
            $circuitBreakerService: '@Tourze\Symfony\CircuitBreaker\Service\CircuitBreakerService'
            $httpClient: '@http_client'
            $servicePrefix: 'http_client_'
            $fallbackFactory: '@App\Service\HttpClientFallbackFactory'



namespace App\Service;

use Symfony\Contracts\HttpClient\ResponseInterface;
use Symfony\Component\HttpClient\Response\MockResponse;

class HttpClientFallbackFactory
{
    public function __invoke(string $method, string $url, array $options): ResponseInterface
    {
        // 根据不同的URL返回不同的降级响应
        if (strpos($url, '/users') !== false) {
            return new MockResponse(json_encode(['users' => []]), [
                'http_code' => 200,
            ]);
        }
        
        // 默认降级响应
        return new MockResponse(json_encode([
            'error' => '服务暂时不可用',
            'fallback' => true,
        ]), [
            'http_code' => 503,
        ]);
    }
}
bash
php bin/console circuit-breaker:status api.users
bash
php bin/console circuit-breaker:status api.users --reset