Circuit Breaker 设计模式的 Swift 实现
这是一个轻量级的 Circuit Breaker 设计模式的 Swift 实现。断路器适用于执行某些可能失败的工作,并希望根据给定的配置或阈值重复执行该工作的情况。当达到阈值时,断路器将跳闸,防止不必要的负载,直到断路器在超时后重置。此实现提供了一种易于使用的方式来监控超时并支持重试逻辑。
您可以使用 CocoaPods 来安装 SGCircuitBreaker
,方法是将其添加到您的 Podfile
platform :ios, '9.0'
use_frameworks
target 'MyApp' do
pod 'SGCircuitBreaker'
end
您可以使用 Carthage 来安装 SGCircuitBreaker
,方法是将其添加到您的 Cartfile
github "eman6576/SGCircuitBreaker"
您可以使用 Swift Package Manager 来安装 SGCircuitBreaker
,方法是将正确的描述添加到您的 Package.swift
文件中
import PackageDescription
let package = Package(
name: "YOUR_PROJECT_NAME",
dependencies: [
.package(url: "https://github.com/eman6576/SGCircuitBreaker.git", .upToNextMajor(from: "1.1.4"))
],
targets: [
.target(
name: "YOUR_TARGET_NAME",
dependencies: [
"SGCircuitBreaker"
]
)
]
)
要访问可用的数据类型,请像这样将 SGCircuitBreaker
导入到您的项目中
import SGCircuitBreaker
我们可以通过两种方式实例化 SGCircuitBreaker
的实例
let circuitBreaker = SGCircuitBreaker()
使用默认配置或像这样
let circuitBreaker = SGCircuitBreaker(
timeout: 20,
maxFailures: 4,
retyDelay: 3
)
对于断路器实例,我们需要注册需要执行的工作
circuitBreaker.workToPerform = { [weak self] (circuitBreaker) in
self?.mockService.call { (data, error) in
guard error == nil else {
circuitBreaker.failure(error: error)
return
}
circuitBreaker.success()
}
}
这里我们注册需要执行的工作。这项工作是调用 mockService
上的一个可能失败的异步方法。在方法 call
的闭包中,我们检查是否发生了错误。如果发生了错误,我们通过调用 circuitBreaker.failure(error: error)
并传递错误来向断路器报告工作失败。这将检查是否已达到最大失败次数。如果尚未达到最大次数,则断路器将等待一段时间,然后再尝试再次执行该工作。断路器将处于 halfOpened
状态。如果达到最大失败次数,则断路器跳闸。如果没有发生错误,那么我们通过调用 circuitBreaker.success()
向断路器报告工作成功。这将将断路器重置为其初始的 closed
状态。
现在,如果断路器跳闸会发生什么。我们希望能够处理这种情况并执行任何必要的错误处理逻辑,而不会破坏我们的应用程序。我们可以像这样注册如何处理断路器跳闸
circuitBreaker.tripped = { (circuitBreaker, error) in
print("Error occured with breaker: \(error)")
}
这里我们注册一个处理程序,用于在断路器跳闸时执行。将传递一个 Error?
,表示最后报告的错误。此时,断路器处于 open
状态。
在某些情况下,您可能需要知道断路器是否成功。这也意味着何时向断路器报告成功。我们可以像这样注册一个处理程序
circuitBreaker.successful { (circuitBreaker) in
print("Circuit breaker was successful")
}
我们还可以处理断路器达到设定的超时时间的情况。我们可以使用它来取消已注册的工作,如下所示
circuitBreaker.timedOut = { [weak self] (circuitBreaker) in
print("Timeout reached")
self?.mockService.cancel()
}
一旦我们设置了处理程序,我们需要像这样启动断路器
circuitBreaker.start()
这是一个断路器如何使用的完整示例
let circuitBreaker = SGCircuitBreaker(
timeout: 20,
maxFailures: 4,
retyDelay: 3
)
circuitBreaker.workToPerform = { [weak self] (circuitBreaker) in
self?.mockService.call { (data, error) in
guard error == nil else {
circuitBreaker.failure(error: error)
return
}
circuitBreaker.success()
}
}
circuitBreaker.tripped = { (circuitBreaker, error) in
print("Error occured with breaker: \(error)")
}
circuitBreaker.successful { (circuitBreaker) in
print("Circuit breaker was successful")
}
circuitBreaker.timedOut = { [weak self] (circuitBreaker) in
print("Timeout reached")
self?.mockService.cancel()
}
circuitBreaker.start()
SGCircuitBreaker
可以使用三个参数进行配置
timeout
: 一个 TimeInterval
,表示已注册的工作在抛出错误之前必须完成的时间长度。默认为 10。maxFailures
: 一个 Int
,表示在跳闸之前允许重试执行已注册工作的最大失败次数。默认为 3。retryDelay
: 一个 TimeInterval
,表示在失败后重试已注册工作之前等待的时间长度。默认为 2。SGCircuitBreaker
包含一些公共方法和属性
start()
: 启动断路器。success()
: 向断路器报告已注册的工作已成功。failure(error: Error? = nil)
: 向断路器报告已注册的工作失败。reset()
: 重置断路器。failureCount
: 当前失败次数。state
: 断路器的当前状态。可以是 open
、halfOpened
或 closed
。SGCircuitBreaker
可以将断路器内部发生的不同事件记录到控制台。默认情况下,此功能未启用。如果您想启用它,可以在创建实例时启用它,如下所示
let circuitBreaker = SGCircuitBreaker(loggingEnabled: true)
您也可以随时更改此属性
circuitBreaker.loggingEnabled = true
当事件被记录时,它在控制台中看起来像这样
SGCircuitBreaker: Registered work was successful. 🎉
请参阅 SGCircuitBreakerTests.swift,了解有关如何使用它的一些示例。
请参阅 贡献文件!
接受 PR。
小提示:如果编辑 Readme,请遵守 standard-readme 规范。