本文目录导读:

我来详细说明Python中熔断器模式的实现方式。
基础熔断器实现
import time
from enum import Enum
from functools import wraps
class CircuitBreakerState(Enum):
CLOSED = "closed" # 正常状态
OPEN = "open" # 熔断状态
HALF_OPEN = "half_open" # 半开状态
class CircuitBreaker:
def __init__(self, failure_threshold=5, recovery_timeout=30, half_open_max_calls=3):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.half_open_max_calls = half_open_max_calls
self.state = CircuitBreakerState.CLOSED
self.failure_count = 0
self.last_failure_time = None
self.half_open_calls = 0
def call(self, func, *args, **kwargs):
if self.state == CircuitBreakerState.OPEN:
if self._should_attempt_recovery():
self.state = CircuitBreakerState.HALF_OPEN
self.half_open_calls = 0
else:
raise Exception("Circuit breaker is OPEN")
try:
result = func(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise e
def _on_success(self):
if self.state == CircuitBreakerState.HALF_OPEN:
self.half_open_calls += 1
if self.half_open_calls >= self.half_open_max_calls:
self.state = CircuitBreakerState.CLOSED
self.failure_count = 0
elif self.state == CircuitBreakerState.CLOSED:
self.failure_count = 0
def _on_failure(self):
self.failure_count += 1
self.last_failure_time = time.time()
if self.state == CircuitBreakerState.HALF_OPEN:
self.state = CircuitBreakerState.OPEN
elif self.failure_count >= self.failure_threshold:
self.state = CircuitBreakerState.OPEN
def _should_attempt_recovery(self):
if self.last_failure_time is None:
return True
return time.time() - self.last_failure_time >= self.recovery_timeout
# 使用示例
def unreliable_service():
import random
if random.random() < 0.7: # 70% 概率失败
raise Exception("Service failed!")
return "Success"
cb = CircuitBreaker(failure_threshold=3, recovery_timeout=10)
for i in range(20):
try:
result = cb.call(unreliable_service)
print(f"Call {i}: {result}")
except Exception as e:
print(f"Call {i}: {e}")
time.sleep(1)
装饰器版本
import time
from functools import wraps
from enum import Enum
class CircuitBreakerDecorator:
def __init__(self, failure_threshold=5, recovery_timeout=30):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.state = "closed"
self.failure_count = 0
self.last_failure_time = None
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
if self.state == "open":
if time.time() - self.last_failure_time >= self.recovery_timeout:
self.state = "half_open"
print("Attempting recovery...")
else:
raise Exception(f"Circuit breaker is OPEN for {func.__name__}")
try:
result = func(*args, **kwargs)
self._handle_success()
return result
except Exception as e:
self._handle_failure()
raise e
return wrapper
def _handle_success(self):
if self.state == "half_open":
self.state = "closed"
self.failure_count = 0
print("Service restored, circuit closed")
elif self.state == "closed":
self.failure_count = 0
def _handle_failure(self):
self.failure_count += 1
self.last_failure_time = time.time()
if self.state == "half_open" or self.failure_count >= self.failure_threshold:
self.state = "open"
print(f"Circuit OPEN after {self.failure_count} failures")
# 使用装饰器
@CircuitBreakerDecorator(failure_threshold=3, recovery_timeout=5)
def api_call():
import random
if random.random() < 0.6:
raise Exception("API call failed")
return "API call succeeded"
# 测试
for i in range(15):
try:
result = api_call()
print(f"Call {i}: {result}")
except Exception as e:
print(f"Call {i}: {str(e)}")
time.sleep(1)
高级版本(支持异步)
import asyncio
import time
from enum import Enum
from functools import wraps
from typing import Callable, Any, Optional
class CircuitBreakerState(Enum):
CLOSED = "closed"
OPEN = "open"
HALF_OPEN = "half_open"
class AdvancedCircuitBreaker:
def __init__(
self,
failure_threshold: int = 5,
recovery_timeout: float = 30.0,
half_open_max_calls: int = 3,
excluded_exceptions: Optional[tuple] = None
):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.half_open_max_calls = half_open_max_calls
self.excluded_exceptions = excluded_exceptions or ()
self.state = CircuitBreakerState.CLOSED
self.failure_count = 0
self.success_count = 0
self.last_failure_time = None
self._lock = asyncio.Lock()
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
pass
async def call_async(self, func: Callable, *args, **kwargs) -> Any:
async with self._lock:
await self._check_state()
try:
if asyncio.iscoroutinefunction(func):
result = await func(*args, **kwargs)
else:
result = func(*args, **kwargs)
await self._on_success()
return result
except self.excluded_exceptions:
raise
except Exception as e:
await self._on_failure()
raise
async def _check_state(self):
if self.state == CircuitBreakerState.OPEN:
if self._should_attempt_recovery():
print("Attempting recovery...")
self.state = CircuitBreakerState.HALF_OPEN
self.success_count = 0
else:
raise Exception("Circuit breaker is OPEN")
async def _on_success(self):
if self.state == CircuitBreakerState.HALF_OPEN:
self.success_count += 1
if self.success_count >= self.half_open_max_calls:
self.state = CircuitBreakerState.CLOSED
self.failure_count = 0
print("Circuit CLOSED - service restored")
elif self.state == CircuitBreakerState.CLOSED:
self.failure_count = 0
async def _on_failure(self):
self.failure_count += 1
self.last_failure_time = time.time()
if self.state == CircuitBreakerState.HALF_OPEN:
self.state = CircuitBreakerState.OPEN
print("Circuit OPEN - recovery failed")
elif self.failure_count >= self.failure_threshold:
self.state = CircuitBreakerState.OPEN
print(f"Circuit OPEN after {self.failure_count} failures")
def _should_attempt_recovery(self):
if self.last_failure_time is None:
return True
return time.time() - self.last_failure_time >= self.recovery_timeout
# 异步使用示例
async def async_api_call():
import random
await asyncio.sleep(0.1)
if random.random() < 0.6:
raise Exception("Async API failed")
return "Async API succeeded"
async def main():
cb = AdvancedCircuitBreaker(
failure_threshold=3,
recovery_timeout=5,
half_open_max_calls=2
)
for i in range(20):
try:
result = await cb.call_async(async_api_call)
print(f"Call {i}: {result}")
except Exception as e:
print(f"Call {i}: {str(e)}")
await asyncio.sleep(1)
# 运行
if __name__ == "__main__":
asyncio.run(main())
使用第三方库(pybreaker)
# pip install pybreaker
import pybreaker
import random
import time
# 创建熔断器实例
breaker = pybreaker.CircuitBreaker(
fail_max=3, # 最大失败次数
reset_timeout=10, # 重置超时(秒)
exclude=[ # 排除的异常类型
ValueError
]
)
# 使用装饰器
@breaker
def unstable_service():
if random.random() < 0.7:
raise ConnectionError("Service unreachable")
return "Service call succeeded"
# 或者使用上下文管理器
def another_service():
with breaker:
if random.random() < 0.7:
raise ConnectionError("Service unreachable")
return "Another service call succeeded"
# 监听器模式
class MyListener(pybreaker.CircuitBreakerListener):
def state_change(self, cb, old_state, new_state):
print(f"State changed from {old_state} to {new_state}")
def failure(self, cb, exc):
print(f"Failure detected: {exc}")
def success(self, cb):
print("Success detected")
breaker_with_listener = pybreaker.CircuitBreaker(
fail_max=3,
reset_timeout=10,
listeners=[MyListener()]
)
# 测试
for i in range(15):
try:
result = unstable_service()
print(f"Call {i}: {result}")
except pybreaker.CircuitBreakerError as e:
print(f"Call {i}: Circuit breaker open")
except Exception as e:
print(f"Call {i}: {str(e)}")
time.sleep(1)
关键设计要点
- 状态管理:CLOSED → OPEN → HALF_OPEN 的状态转换
- 失败计数:统计连续失败次数
- 超时恢复:自动尝试恢复服务
- 半开测试:部分允许请求来测试服务是否恢复
- 异常处理:可配置排除某些异常
选择哪种实现取决于你的具体需求:
- 简单场景:使用基础版本
- 需要装饰器:使用装饰器版本
- 异步应用:使用异步版本
- 生产环境:推荐使用成熟的第三方库如
pybreaker
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播