Kitura

APIDoc Build Status - Master macOS Linux Apache 2 Slack Status

熔断器 (CircuitBreaker)

熔断器设计模式用于提高应用程序的稳定性,缩短响应时间,并防止应用程序持续发送失败的请求。 该库提供了将熔断器逻辑引入 Swift 应用程序所需的工具。

Circuit Breaker Diagram

Swift 版本

最新版本的 CircuitBreaker 可与 5.1 及更高版本的 Swift 二进制文件一起使用。 您可以通过以下链接下载此版本的 Swift 二进制文件。

入门指南

CircuitBreaker 添加到应用程序的 Package.swift 文件中的依赖项。 使用最新的 CircuitBreaker 发布版本 替换 "x.x.x"

.package(url: "https://github.com/Kitura/CircuitBreaker.git", from: "x.x.x")

CircuitBreaker 添加到你的目标的依赖项

.target(name: "example", dependencies: ["CircuitBreaker"]),

在你的应用程序中导入包

import CircuitBreaker

用法

CircuitBreaker 的状态基于超时和用户定义的失败(当你要熔断的函数进行异步调用时非常有用)。 要在应用程序代码中使用 CircuitBreaker,你需要执行以下操作

func myFallback(err: BreakerError, msg: String) {
    // The fallback will be called if one of the below occurs:
    //  1. The request does not return before the specified timeout
    //  2. CircuitBreaker is currently in Open state and set to fail fast.
    //  3. There was an error in the user's called context function (networking error, etc.)
    Log.verbose("Error: \(err)")
    Log.verbose("Message: \(msg)")
}
extension BreakerError {
    public static let encodingURLError = BreakerError(reason: "URL could not be created")
    public static let networkingError = BreakerError(reason: "There was an error, while sending the request")
    public static let jsonDecodingError = BreakerError(reason: "Could not decode result into JSON")
}
func myContextFunction(invocation: Invocation<(String), String>) {
  let requestParam = invocation.commandArgs
  // Create HTTP request
  guard let url = URL(string: "http://myserver.net/path/\(requestParam)") else {
    // Something went wrong

    invocation.notifyFailure(error: .encodingURLError)
    return
  }

  var req = URLRequest(url: url)
  req.httpMethod = "GET"
  let session = URLSession.shared

  // Perform the request
  session.dataTask(with: req) { result, res, err in
    guard let result = result else {
      // Failed getting a result from the server

      invocation.notifyFailure(error: .networkingError)
      return
    }

    // Convert results to a JSON object
    guard let json = (try? JSONSerialization.jsonObject(with: result, options: [])) as? [String: Any] else {
      invocation.notifyFailure(error: .jsonDecodingError)
      return
    }
    // Process JSON data

    invocation.notifySuccess()
  }.resume()
}
let breaker = CircuitBreaker(name: "Circuit1", command: myContextFunction, fallback: myFallback)
let requestParam: String = "myRequestParams"
breaker.run(commandArgs: requestParam, fallbackArgs: "Something went wrong.")

完整实现

extension BreakerError {
    public static let encodingURLError = BreakerError(reason: "URL could not be created")
    public static let networkingError = BreakerError(reason: "There was an error, while sending the request")
    public static let jsonDecodingError = BreakerError(reason: "Could not decode result into JSON")
}

func myFallback(err: BreakerError, msg: String) {
    // The fallback will be called if one of the below occurs:
    //  1. The request does not return before the specified timeout
    //  2. CircuitBreaker is currently in Open state and set to fail fast.
    //  3. There was an error in the user's called context function (networking error, etc.)
    Log.verbose("Error: \(err)")
    Log.verbose("Message: \(msg)")
}

func myContextFunction(invocation: Invocation<(String), String>) {
  let requestParam = invocation.commandArgs
  // Create HTTP request
  guard let url = URL(string: "http://mysever.net/path/\(requestParam)") else {
    // Something went wrong...

    invocation.notifyFailure(error: .encodingURLError)
  }

  var req = URLRequest(url: url)
  req.httpMethod = "GET"
  let session = URLSession.shared

  // Perform Request
  session.dataTask(with: req) { result, res, err in
    guard let result = result else {
      // Failed getting a result from the server

      invocation.notifyFailure(error: .networkingError)
      return
    }

    // Convert results to a JSON object
    guard let json = (try? JSONSerialization.jsonObject(with: result, options: [])) as? [String: Any] else {
        invocation.notifyFailure(error: .jsonDecodingError)
        return
    }
    // Process JSON data

    invocation.notifySuccess()
  }.resume()
}

let breaker = CircuitBreaker(name: "Circuit1", command: myContextFunction, fallback: myFallback)

let requestParam: String = "myRequestParams"
breaker.run(commandArgs: requestParam, fallbackArgs: "Something went wrong.")

统计信息

将为 CircuitBreaker 实例跟踪以下统计信息

跟踪的统计信息

下面的示例代码展示了如何记录统计信息的快照以及如何创建符合 Hystrix 标准的快照。

// Create CircuitBreaker
let breaker = CircuitBreaker(name: "Circuit1", command: myFunction, fallback: myFallback)

// Invoke breaker call
breaker.run(commandArgs: (a: 10, b: 20), fallbackArgs: "Something went wrong.")

// Log statistics snapshot
breaker.logSnapshot()

// Hystrix compliant snapshot
let snapshot = breaker.snapshot

观察统计信息

CircuitBreaker 库提供了一个接口,用于观察新的 CircuitBreaker 实例,以便注册和跟踪统计信息的变化。 在初始化 CircuitBreaker 实例时,会通知链接的监视器其实例化,从而允许它们开始跟踪实例的统计信息。 CircuitBreaker 实例向监视器公开符合 Hystrix 标准的统计信息快照,然后可以对其进行相应处理。 有关更多信息,请参阅 API 文档。

API 文档

有关更多信息,请访问我们的 API 参考

社区

我们很乐意讨论服务器端 Swift 和 Kitura。 加入我们的 Slack 与团队会面!

许可证

此 Swift 包已获得 Apache 2.0 许可。 完整的许可文本可在 LICENSE 中找到。