# @bennadel/circuit-breaker 中文文档

规范地址：https://npmcn.com/package/%40bennadel/circuit-breaker/

版本：0\.0\.1
npm 元数据更新时间：2022-06-12T15:10:52.109Z
中文译文更新时间：2026-11-07T22:21:52.264Z
软件包许可：ISC

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40bennadel/circuit-breaker
原文对照：https://npmcn.com/package/%40bennadel/circuit-breaker/?lang=original
项目主页：https://github.com/bennadel/Node-Circuit-Breaker#readme
源码仓库：https://github.com/bennadel/Node-Circuit-Breaker

## 关键信息（来自 npm 元数据）

- 模块格式：CommonJS
- TypeScript 类型：未声明
- 运行依赖：0 个
- 首次发布：2017-07-10T10:20:24.738Z
- 最新版本发布：2017-07-10T10:20:24.738Z
- 近 30 天下载量：13084（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：1（近 12 个月 0 个）

## 中文简介

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

## 安装

```sh
npm install @bennadel/circuit-breaker
```

也可以使用：`pnpm add @bennadel/circuit-breaker`、`yarn add @bennadel/circuit-breaker`、`bun add @bennadel/circuit-breaker`

## README

# 节点断路器

以 [本·纳德尔](http://www.bennadel.com/) 联 合 国 [谷歌+ (韩语)](https://plus.google.com/108976367067760160494?rel=author)(中文(简体) )

这是一个 **节点.js** 执行情况 **断路器** 大众化模式 内 [迈克尔·T·尼加德的书——发行!](https://www.bennadel.com/blog/3162-release-it-design-and-deploy-production-ready-software-by-michael-t-nygard.htm)。用于断路器 用于代用上游资源的消耗,以致上游资源的失败 以可预测的方式向现有系统进行宣传。 清楚一点,断路器 无法防止失败;相反,它帮助您的应用程序主动管理失败, 未快速和/或酌情提供倒数.

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

## 默认使用

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

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

```js
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`。 。 。 . 这也是断路器需要的时间 **继续打开** 之后 在允许执行“ 健康检查” 请求之前失败 ._

```js
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
});
```

## 倒计时值

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

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

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

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

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

```js
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) 伐木).

```js
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` 参数 :

```js
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()` 方法 :

```js
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*` 方法:

```js
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` 默认提供的 采用下列结构:

```json
{
    "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`数字 :

```js
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 是什么？

用于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 和提交记录判断。

