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