@bennadel/circuit-breaker

中文文档
0.0.1发布于 2017/07/10ISCCommonJS零依赖近 30 天下载 1.3万

用于Node.js的柔性断路器(需要ES6类模块).

中文使用文档
文档目录9 节
  1. 默认使用
  2. 配置用途
  3. 倒计时值
  4. 断路器很吓人 - 如果我弄错了怎么办?
  5. 记录和监测
  6. 建设你自己 State 执行情况
  7. 围绕同步状态跟踪的保证
  8. 所有计量应该存储在记忆中
  9. 软件包导出

节点断路器

以 本·纳德尔 联 合 国 谷歌+ (韩语)(中文(简体) )

这是一个 节点.js 执行情况 断路器 大众化模式 内 迈克尔·T·尼加德的书——发行!。用于断路器 用于代用上游资源的消耗,以致上游资源的失败 以可预测的方式向现有系统进行宣传。 清楚一点,断路器 无法防止失败;相反,它帮助您的应用程序主动管理失败, 未快速和/或酌情提供倒数.

断路器代表上游资源的消耗;但是,它没有 熟悉上游资源。 因此,断路器的范围 可以是路线,也可以是颗粒体,只要你认为合适。 比如,你可以拥有 一个代表整个上游资源的断路器。 或者,你可以创建一个 单个断路器 每种方法 在上游资源。 颗粒越多 你的断路器,你得到假阳性的可能性越小.

默认使用

每个断路器是由数个物体组成的,它们共同提供 跟踪和故障快速功能。 幸运的是,你不必知道 除非您正在构建自定义执行。 你只需要问 带有指定设置的断路器厂实例 .

创建断路器最简单的方式是创建一个完全没有设置的断路器. 这样做将创建一个带有"好"默认的断路器:

var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

var circuitBreaker = CircuitBreakerFactory.create();

// Invoke as closure.
circuitBreaker.execute(
    function() {
        return( upstreamResource.load() );
    }
);

// Invoke as closure with context and arguments.
circuitBreaker.executeInContext(
    upstreamResource,
    function( param1, param2 ) {
        return( this.load( param1, param2 ) );
    },
    [ "arg1", "arg2" ]
);

// Invoke as method on an object.
circuitBreaker.executeMethod( upstreamResource, "load", [ "arg1", "arg2" ] );

如您所见,通过断路器运行命令有三种方式:

  • execute( command [, fallback ] )
  • executeInContext( context, command [, args [, fallback ] ] )
  • executeMethod( context, methodName [, args [, fallback ] ] )

每个 execute* 方法返回一个承诺,如果解析 执行是成功的;或者,如果执行错误(或 根据断路器的状态绕行。 基本方法/函数 正在被引用的,应当返回承诺或同步值。 或者,它可以省略一个 如果不需要,则返回.

配置用途

这个 .create() 电路断路器制造厂的方法毫无争议, 您可以提供用于生成断路器的散列设置. 以下每个设置都是 选项数字 :

  • id - 基本国家实例的独特标识,用于 伐木业.
  • requestTimeout - 允许悬吊待决请求的时间(以毫秒计) 在错误中被超时之前( 未完成 ) .
  • volumeThreshold - 需要完成的请求数量(在 滚动度量衡窗口),然后才能计算出失败百分比.
  • failureThreshold - 可能发生的故障的百分比(全部数字) 在断路器开关状态前滚动参数窗口 打开。 。 。 .
  • activeThreshold - 可挂起的并行请求数量(即,不完全) 在断路器切换到 打开。 。 。 .
  • isFailure - 确定给定失败是否为错误的函数;或 它应被归类为成功(例如404个答复).
  • fallback - 用于断路器所有处决的全球倒计时 (每次处决都可以在当地推翻).
  • monitor - 外部记录(前StatsD记录)的显示器 -- -- 函数或实例.
  • bucketCount - 用于收集滚动统计数据的桶数 滚动度量衡窗口.
  • bucketDuration - 滚动内每桶的长度(以毫秒计) 度量衡窗口.

页:1:滚动度量衡窗口的持续时间为 bucketCount * bucketDuration。 。 。 . 这也是断路器需要的时间 继续打开 之后 在允许执行“ 健康检查” 请求之前失败 .

var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

var circuitBreaker = CircuitBreakerFactory.create({
    id: "Remote API",
    requestTimeout: 5000,
    volumeThreshold: 10,
    failureThreshold: 10, // Percent (as in 1 failure in 10 responses trips the circuit).
    activeThreshold: 50,
    isFailure: function( error ) {
        return( ! is404( error ) );
    },
    fallback: { /* Fallback value. */ },
    monitor: function( eventType, eventData ) {
        console.log( eventType, eventData );
    },
    bucketCount: 30,
    bucketDuration: 1000
});

倒计时值

电路断路器的首要目标是 如果上游资源"失效" 看起来不健康 然而,"断路器"的次要目标是提供 一个更好的用户体验。 这意味着,如果能够提供有意义的回落值 如果出现错误,电路断路器将促进这一办法.

倒置值可以是函数值,承诺值,也可以是任何静态值. 如果是一个函数, 它应该返回一个承诺或一个静态值。 当 创建断路器 :

var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

var circuitBreaker = CircuitBreakerFactory.create({
    id: "Remote API",
    fallback: { /* Fallback value. */ }
});

但是,它们也可以在处决时提供(无论是否提供) 提供了全球回落值 :

var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

var circuitBreaker = CircuitBreakerFactory.create({
    id: "Remote API",
    fallback: { /* Fallback value. */ }
});

circuitBreaker
    .execute(
        function() {
            throw( new Error( "Network Error" ) );
        },
        { /* Local fallback value. */ }
    )
    .then(
        function( result ) {
            console.log( result ); // Will be LOCAL fallback value.
        }
    )
;

如果倒计时值是函数,则执行提供了 上下文 财务报告和审定财务报表 参数,同样的 上下文 财务报告和审定财务报表 参数 将用来引用后退.

断路器很吓人 - 如果我弄错了怎么办?

老实说,它可能是可怕的 - 将一些东西投入生产的想法 故意阻断代理系统的通话 如果你选择一个错误阈值,那就是 太低了, 你可能会太快地开始屏蔽请求 。 如果选择活动阈值 那太高了,你可能会把上游资源挖出来.

幸运的是,你不必直接潜入深端。 相反,你可以部署一个 被动断路器 它将记录所有的交通, 永远不会失败打开, (中文(简体) ), 不管上游资源变得多么不健康 这样的话,你可以花点时间 被动收集有关您 API 使用情况( 包括计数、 持续时间和 错误),在切换到带有特制设置的活性断路器之前.

由于这是一个被动电路断路器(从不打开),设置较少:

  • id - 基本国家实例的独特标识,用于 伐木业.
  • isFailure - 确定给定失败是否为错误的函数;或 它应被归类为成功(例如404个答复).
  • fallback - 用于断路器所有处决的全球倒计时 (每次处决都可以在当地推翻).
  • monitor - 外部记录的显示器 -- -- 函数或实例(前StatsD) 伐木).
var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

var circuitBreaker = CircuitBreakerFactory.createPassive({
    id: "Remote API",
    monitor: function logEvent( eventType, eventData ) {
        // Log statsD metrics about count and duration.
        // Log errors.
    }
});

// This error will result in a rejected promise; but, the Circuit Breaker will always
// remain closed, allowing requests to be executed.
circuitBreaker.execute(
    function() {
        throw( new Error( "Network Error" ) );
    }
);

一旦你有机会 监视你的断路器, 你可以开始切换你的 .createPassive() 工厂电话 .create() 使用您设置的厂房呼叫 知与所收集的度量基准相对应。 你可以晚上好好睡一觉.

记录和监测

默认情况下,"断路器"悄悄地丢弃了所有内部事件. 不过,你会 可能想要在您的应用程序中日志错误并记录 StatsD 参数 。 为了做到这一点, 您可以提供一个日志函数作为 monitor 参数 :

var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

var circuitBreaker = CircuitBreakerFactory.create({
    id: "Remote API",
    monitor: function logEvent( eventType, eventData ) {
        console.log( eventType, eventData );
    }
});

此日志函数将调用如下 eventType值 :

  • closed 过 eventData 属性 { stateSnapshot }
  • execute 过 eventData 属性 { stateSnapshot }
  • emit 过 eventData 属性 { stateSnapshot }
  • failure 过 eventData 属性 { stateSnapshot, duration, error }
  • fallbackEmit 过 eventData 属性 { stateSnapshot }
  • fallbackFailure 过 eventData 属性 { stateSnapshot, error }
  • fallbackMissing 过 eventData 属性 { stateSnapshot }
  • fallbackSuccess 过 eventData 属性 { stateSnapshot }
  • opened 过 eventData 属性 { stateSnapshot }
  • shortCircuited 过 eventData 属性 { stateSnapshot, error }
  • success 过 eventData 属性 { stateSnapshot, duration }
  • timeout 过 eventData 属性 { stateSnapshot, duration, error }

盖子下面,这实际上是用你的 logEvent() 完成混凝土的功能 执行情况 AbstractLoggingMonitor。如果不提供函数,则可以 提供扩展 Monitor 类或 AbstractLoggingMonitor 课。 如果你延长 AbstractLoggingMonitor 基础类,您只需覆盖 页:1 logEvent() 方法 :

var AbstractLoggingMonitor = require( "@bennadel/circuit-breaker" ).AbstractLoggingMonitor;
var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;

class MyMonitor extends AbstractLoggingMonitor {

    constructor( statsD ) {

        super();
        this._statsD = statsD;

    }

    logEvent( eventType, eventData ) {

        stats.increment( `circuit-breaker.${ eventType }` );

    }

}

// ....

var circuitBreaker = CircuitBreakerFactory.create({
    id: "Remote API",
    monitor: new MyMonitor( stats )
});

但是,如果你延长 Monitor 类,可以覆盖任意一个 log* 方法:

var CircuitBreakerFactory = require( "@bennadel/circuit-breaker" ).CircuitBreakerFactory;
var Monitor = require( "@bennadel/circuit-breaker" ).Monitor;

class MyMonitor extends Monitor {
    
    logClosed( stateSnapshot ) {
        /* ... */
    }

    logOpened( stateSnapshot ) {
        /* ... */
    }

}

// ....

var circuitBreaker = CircuitBreakerFactory.create({
    id: "Remote API",
    monitor: new MyMonitor()
});

这个 Monitor class 提供了以下默认, 不操作( no Operation) 方法, 该方法 表示您只需覆盖对您的应用程序有意义的程序 :

  • logClosed( stateSnapshot ) 我记录了断路器的状态 从打开到关闭.
  • logExecute( stateSnapshot ) - 我记录了死刑执行地点 电路断路器的状态和基础命令即将被引用.
  • logEmit( stateSnapshot ) 我记录请求输入时点 断路器尚未被批准执行.
  • logFailure( stateSnapshot, duration, error ) - 我记录一下.. 执行已以错误结束 。 这只反映了非循环断路器出错 (参见日志Timeout()和日志Short Circuted()事件).
  • logFallbackEmit( stateSnapshot ) 我记录了一个失败者 执行(由于错误、超时或短路) 反击.
  • logFallbackFailure( stateSnapshot, error ) - 我记录了一个存在 返回函数在错误中解析 .
  • logFallbackMissing( stateSnapshot ) 我记录了一次失败的行刑地点 没有定义后退.
  • logFallbackSuccess( stateSnapshot ) 我记录了一个倒数值的倒数点 成功支持失败或绕过执行 .
  • logOpened( stateSnapshot ) 我记录了断路器的状态 从关闭到打开.
  • logShortCircuited( stateSnapshot, error ) -我记录了处决地点 绕行是因为电路断路器目前处于打开状态.
  • logSuccess( stateSnapshot, duration ) - 我记录了处决地点 成功解决.
  • logTimeout( stateSnapshot, duration, error ) - 我记录到一个很长的时间 运行中的执行已明确在错误中超时.

这个 stateSnapshot 对象传递到 Monitor 方法(以及 AbstractLoggingMonitor logEvent() 方法) 包含识别和计量 关于利用国家为断路器提供动力的信息。 由于一个电路 断路器可以和另一个断路器共享状态,在 因此,国家成为有意义的国家 用于伐木和监测的信息。 每个 stateSnapshot 默认提供的 采用下列结构:

{
    "id": "Circuit Breaker for API",
    "closed": true,
    "settings": {
        "requestTimeout": 0,
        "volumeThreshold": 0,
        "failureThreshold": 0,
        "activeThreshold": 0
    },
    "metrics": {
        "emit": 0,
        "execute": 0,
        "success": 0,
        "failure": 0,
        "timeout": 0
    },
    "totalMetrics": {
        "emit": 0,
        "execute": 0,
        "success": 0,
        "failure": 0,
        "timeout": 0
    },
    "current": {
        "activeRequestCount": 0
    }
}

建设你自己 State 执行情况

电路断路器被设计成由多个不同类别组成的复合体 共同努力实现一个目标。 这种构成的原因是允许 如果需要,将设计自定义执行。 理想的,如果你想习惯 执行,你应该提供的唯一类是 State 课。 这个 CircuitBreaker 类管理控制流;但是,它使用 State 执行 使控制流动的力量。 如果你想提供自己的 State 执行,你 必须提供一种能暴露以下方法的类:

  • canPerformHealthCheck()
  • getSnapshot()
  • isOpened()
  • isClosed()
  • getTimeout()
  • trackExecute()
  • trackEmit()
  • trackFailure( duration, error )
  • trackFallbackEmit()
  • trackFallbackFailure( error )
  • trackFallbackMissing()
  • trackFallbackSuccess()
  • trackShortCircuited( error )
  • trackSuccess( duration )
  • trackTimeout( duration, error )

这些方法中你的行为完全由你决定。 但是,它们必须存在 页:1 CircuitBreaker 会打电话给他们。 用于控制 CircuitBreaker 根据这项计划:

  • 顶级 execute*() 方法被称为.
  • 打电话 trackEmit()。 。 。 .
  • 检查是否 isOpened()。 。 。 .
  • 如果打开 :
    • 检查是否 canPerformHealthCheck()
      • 如果能够进行健康检查,则执行.
  • 如果能够执行命令 :
    • 打电话 trackExecute()。 。 。 .
    • 使用设置超时计时器 getTimeout()。 。 。 .
    • 启动基本命令.
  • 关于决议:
    • 打电话 trackSuccess()。 。 。 .
  • 关于拒绝:
    • 检查出错类型 :
      • 若为 OpenError 调用 trackShortCircuited()。 。 。 .
      • 若为 TimeoutError 调用 trackTimeout()。 。 。 .
      • 否则打电话 trackFailure()。 。 。 .
    • 打电话 trackFallbackEmit()。 。 。 .
    • 检查是否提供了倒计时(当地或全球) .
      • 如果提供退后:
        • 执行倒计时.
        • 关于决议:
          • 打电话 trackFallbackSuccess()。 。 。 .
        • 关于拒绝:
          • 打电话 trackFallbackFailure()。 。 。 .
      • 如不提供回扣:
        • 打电话 trackFallbackMissing()。 。 。 .

一旦你习惯了 State ,您可以构建一个 CircuitBreaker数字 :

var CircuitBreaker = require( "@bennadel/circuit-breaker" ).CircuitBreaker;

var state = new CustomStateImplementation();

var circuitBreaker = new CircuitBreaker( state [, globalFallback] );

围绕同步状态跟踪的保证

由于电路断路器 生成并返回承诺 围绕执行黑色 - 框式命令,许多方法 State 将引用实例 一个同步。 然而,以下一系列方法是: 保证可以援引 同步 在节点.js事件回路的同一勾选内 :

  • trackEmit()
  • isOpened()
  • canPerformHealthCheck() - 只有在 isOpened() 返回时 true。 。 。 .
  • trackExecute()

由于Node.js运行在一个单一的过程中,你可以假设这四种方法将是 没有任何种族条件.

所有计量应该存储在记忆中

如果你正在建造自己的 State 执行中,您可能会尝试共享度量衡 跨越不同的节点.js进程(或机器). 例如,你可能会被诱惑 在共享的 Redis 实例中存储可消耗的度量衡是每个实例 代表单一资源的断路器. 不要这样做。不仅 需要断路器 State 同步运行的方法;但是,试图共享状态 没有提供真正的增值。 由于故障跟踪基于 百分比共享 状态不会使百分比更准确。 事实上,跨进程共享状态 如果某一程序或机器出现问题(例如: 作为不影响其他进程或机器的配置问题).

软件包导出

此断路器包输出以下公共成员:

  • OpenError
  • StateError
  • TimeoutError
  • Metrics
  • AbstractLoggingMonitor
  • Monitor
  • State
  • CircuitBreaker
  • CircuitBreakerFactory

版本与发布记录

@bennadel/circuit-breaker 共发布 1 个版本,首次发布于 2017/07/10;过去 12 个月发布了 0 个版本。

版本发布日期距今
0.0.1latest2017/07/109 年前

关于 @bennadel/circuit-breaker 的常见问题

@bennadel/circuit-breaker 是什么?

用于Node.js的柔性断路器(需要ES6类模块).

如何安装 @bennadel/circuit-breaker?

在项目目录运行 npm install @bennadel/circuit-breaker,或使用 pnpm add / yarn add / bun add。

@bennadel/circuit-breaker 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/bennadel__circuit-breaker 是否存在。

@bennadel/circuit-breaker 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@bennadel/circuit-breaker 可以商用吗?

@bennadel/circuit-breaker 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bennadel/circuit-breaker 的下载量有多少?

根据 npm 官方下载统计,@bennadel/circuit-breaker 在 2026/10/08 – 2026/11/06 这 30 天内被下载 13,084 次,日均约 436 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bennadel/circuit-breaker 还在维护吗?

最新版本 0.0.1 发布于 2017/07/10(9 年前);至今共发布 1 个版本,其中过去 12 个月发布了 0 个;首次发布于 2017/07/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。