SwiftUI 断路器与网络弹性模式(防止级联故障)
Source: Dev.to
大多数应用都会这样调用 API:
try await api.fetchUser()这样可以正常工作……直到服务器开始出现故障。此时你的应用可能会:
- 立即重试
- 发送数百个失败的请求
- 消耗电池电量
- 给后端造成过载
- 使 UI 变慢
- 加剧故障的影响
这被称为 cascading failure(级联故障)。生产环境的应用需要相应的保护机制。
🧠 核心原则
当系统出现故障时,停止让情况更糟。系统应当检测到故障并暂停请求,而不是无休止地重试。
🧱 1. 什么是断路器?
断路器可以防止对出现故障的服务进行重复调用。它有三种状态:
Closed → Normal operation
Open → Requests blocked
Half-Open → Testing recovery流程
Requests Fail
→ Circuit Opens
→ Requests Blocked
→ Recovery Test
→ Circuit Closes🔌 2. 定义电路状态
enum CircuitState {
case closed
case open(until: Date)
case halfOpen
}- Closed → 允许请求
- Open → 暂时阻止请求
- Half‑Open → 允许有限请求以测试恢复
🧬 3. 基本断路器实现
final class CircuitBreaker {
private(set) var state: CircuitState = .closed
private var failureCount = 0
private let failureThreshold = 5
private let timeout: TimeInterval = 30
func recordFailure() {
failureCount += 1
if failureCount >= failureThreshold {
state = .open(until: Date().addingTimeInterval(timeout))
}
}
func recordSuccess() {
failureCount = 0
state = .closed
}
}故障会累计,直至断路器打开。
🚦 4. 当电路打开时阻止请求
在执行请求之前:
func canExecute() -> Bool {
switch state {
case .closed:
return true
case .open(let until):
return Date() > until
case .halfOpen:
return true
}
}用法
guard breaker.canExecute() else {
throw NetworkError.circuitOpen
}这可以保护后端。
🔄 5. 转为半开
当超时时间到期时:
case .open(let until):
if Date() > until {
state = .halfOpen
return true
}只有少量请求应当用于测试恢复。如果它们成功 → 关闭电路;如果它们失败 → 重新打开。
🔋 6. 为什么移动应用需要断路器
移动网络不稳定。常见的故障场景包括:
- 服务器宕机
- DNS 问题
- TLS 失败
- 限流
- 蜂窝网络丢包
如果没有断路器,您的应用可能会:
- 向后端发送大量请求
- 快速耗尽电池
- 放大故障影响
断路器可以防止这些问题。
🧱 7. 与 API 客户端集成
包装网络调用:
func performRequest(_ operation: () async throws -> T) async throws -> T {
guard breaker.canExecute() else {
throw NetworkError.circuitOpen
}
do {
let result = try await operation()
breaker.recordSuccess()
return result
} catch {
breaker.recordFailure()
throw error
}
}这使得弹性自动化。
🌐 8. 与重试策略相结合
断路器可以与重试一起使用。示例流程:
Request
→ Failure
→ Retry (exponential backoff)
→ Failure threshold reached
→ Circuit opens
→ Requests paused这可以防止重试风暴。
🧪 9. 测试断路器
Test scenarios:
- repeated server errors
- timeout storms
- network disconnections
- recovery after outage
- half‑open transition
Verify that:
- requests stop during outages
- requests resume after recovery
⚠️ 10. 常见反模式
Avoid:
- infinite retries
- retrying immediately after failure
- ignoring server rate limits
- retrying while offline
- not tracking failure counts
These cause backend overload, cascading outages, and battery drain.
🧠 Mental Model
Request
→ Failure Detection
→ Circuit Breaker
→ Pause Requests
→ Recovery Probe
→ Resume Traffic不要:“仅仅再次重试”。
🚀 最终思考
断路器为您的应用提供:
- 后端保护
- 更智能的重试行为
- 降低电池消耗
- 在故障期间的弹性
- 可预测的恢复