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 release 替换 "x.x.x"

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

CircuitBreaker 添加到您的目标的依赖项中

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

在您的应用程序中导入该包

import 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 中找到。