0

0

深入浅析Node.js中的断路器机制

青灯夜游

青灯夜游

发布时间:2021-10-18 09:53:55

|

2265人浏览过

|

来源于掘金社区

转载

本篇文章带大家了解一下node.js中的断路器机制,希望对大家有所帮助!

深入浅析Node.js中的断路器机制

架构演变带来的问题

当我们使用传统的 CS 架构时,服务端由于故障等原因将请求堵塞,可能会导致客户端的请求失去响应,进而在一段时间后导致一批用户无法获得服务。而这种情况可能影响范围是有限,可以预估的。

然而,在微服务体系下,您的服务器可能依赖了若干其他微服务,而这些微服务又依赖其它更多的微服务,这种情况下,某个服务对于下游的堵塞,可能会瞬间(数秒内)因为级联的资源消耗造成整条链路上灾难性的后果,我们称之为“服务血崩”。【推荐学习:《nodejs 教程》】

1.png

2.png

解决问题的几种方式

  • 熔断模式:顾名思义,就如同家用电路一样,如果一条线路电压过高,保险丝会熔断,防止火灾。在使用熔断模式的系统中,如果发现上游服务调用慢,或者有大量超时的时候,直接中止对于该服务的调用,直接返回信息,快速释放资源。直至上游服务好转时再恢复调用。

  • 隔离模式:将不同的资源或者服务的调用分割成几个不同的请求池,一个池子的资源被耗尽并不会影响其它资源的请求,防止某个单点的故障消耗完全部的资源。这是非常传统的一种容灾设计。
  • 限流模式:熔断和隔离都是一种事后处置的方式,限流模式则可以在问题出现之前降低问题出现的概率。限流模式可以对某些服务的请求设置一个最高的 QPS 阈值,超出阈值的请求直接返回,不再占用资源处理。但是限流模式,并不能解决服务血崩的问题,因为往往引起血崩并不是因为请求的数量大,而是因为多个级联层数的放大。

断路器的机制和实现

断路器的存在,相当于给了我们一层保障,在调用稳定性欠佳,或者说很可能会调用失败的服务和资源时,断路器可以监视这些错误并且在达到一定阈值之后让请求失败,防止过度消耗资源。并且,断路器还拥有自动识别服务状态并恢复的功能,当上游服务恢复正常时,断路器可以自动判断并恢复正常请求。

让我们看一下一个没有断路器的请求过程: 用户依赖 ServiceA 来提供服务,ServiceA 又依赖 ServiceB 提供的服务,假设 ServiceB 此时出现了故障,在 10 分钟内,对于每个请求都会延迟 10 秒响应。

3.png

那么假设我们有 N 个 User 在请求 ServiceA 的服务时,几秒钟内,ServiceA 的资源就会因为对 ServiceB 发起的请求被挂起而消耗一空,从而拒绝 User 之后的任何请求。对于用户来说,这就等于 ServiceA 和 ServiceB 同时都出现了故障,引起了整条服务链路的崩溃。

而当我们在 ServiceA 上装上一个断路器后会怎么样呢?

  • 断路器在失败次数达到一定阈值后会发现对 ServiceB 的请求已经无效,那么此时 ServiceA 就不需要继续对 ServiceB 进行请求,而是直接返回失败,或者使用其他Fallback 的备份数据。此时,断路器处于 开路 状态。

  • 在一段时间过后,断路器会开始定时查询 ServiceB 是否已经恢复,此时,断路器处于 半开 状态。

  • 如果 ServiceB 已经恢复,那么断路器会置于 关闭 状态,此时 ServiceA 会正常调用 ServiceB 并且返回结果。

    Tago AI
    Tago AI

    AI生成带货视频,专为电商卖货而生

    下载

4.png

断路器的状态图如下:

5.png

由此可见,断路器的几个核心要点如下:

  • 超时时间:请求达到多久,算引起了一次失败

  • 失败阈值:即断路器触发开路之前,需要达到的失败次数

  • 重试超时:当断路器处于开路状态后,隔多久开始重新尝试请求,即进入半开状态

有了这些知识,我们可以尝试创建一个断路器:

class CircuitBreaker {
  constructor(timeout, failureThreshold, retryTimePeriod) {
    // We start in a closed state hoping that everything is fine
    this.state = 'CLOSED';
    // Number of failures we receive from the depended service before we change the state to 'OPEN'
    this.failureThreshold = failureThreshold;
    // Timeout for the API request.
    this.timeout = timeout;
    // Time period after which a fresh request be made to the dependent
    // service to check if service is up.
    this.retryTimePeriod = retryTimePeriod;
    this.lastFailureTime = null;
    this.failureCount = 0;
  }
}

构造断路器的状态机:

async call(urlToCall) {
    // Determine the current state of the circuit.
    this.setState();
    switch (this.state) {
      case 'OPEN':
      // return  cached response if no the circuit is in OPEN state
        return { data: 'this is stale response' };
      // Make the API request if the circuit is not OPEN
      case 'HALF-OPEN':
      case 'CLOSED':
        try {
          const response = await axios({
            url: urlToCall,
            timeout: this.timeout,
            method: 'get',
          });
          // Yay!! the API responded fine. Lets reset everything.
          this.reset();
          return response;
        } catch (err) {
          // Uh-oh!! the call still failed. Lets update that in our records.
          this.recordFailure();
          throw new Error(err);
        }
      default:
        console.log('This state should never be reached');
        return 'unexpected state in the state machine';
    }
  }

补充剩余功能:

// reset all the parameters to the initial state when circuit is initialized
  reset() {
    this.failureCount = 0;
    this.lastFailureTime = null;
    this.state = 'CLOSED';
  }

  // Set the current state of our circuit breaker.
  setState() {
    if (this.failureCount > this.failureThreshold) {
      if ((Date.now() - this.lastFailureTime) > this.retryTimePeriod) {
        this.state = 'HALF-OPEN';
      } else {
        this.state = 'OPEN';
      }
    } else {
      this.state = 'CLOSED';
    }
  }

  recordFailure() {
    this.failureCount += 1;
    this.lastFailureTime = Date.now();
  }

使用断路器时,只需要将请求包裹在断路器实例中的 Call 方法里调用即可:

...
const circuitBreaker = new CircuitBreaker(3000, 5, 2000);

const response = await circuitBreaker.call('http://0.0.0.0:8000/flakycall');

成熟的 Node.js 断路器库

Red Hat 很早就创建了一个名叫 Opossum 的成熟 Node.js 断路器实现,链接在此:Opossum 。对于分布式系统来说,使用这个库可以极大提升你的服务的容错能力,从根本上解决服务血崩的问题。

原文地址:https://juejin.cn/post/7019217344601948173作者:ES2049 / 寻找奇点

更多编程相关知识,请访问:编程视频!!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
node.js调试
node.js调试

node.js调试可以使用console.log()输出调试信息、断点调试和第三方调试工具。详细介绍:1、console.log()输出调试信息,通过在代码中插入console.log()语句,开发人员可以在控制台输出变量的值、函数的执行结果等信息,以便观察代码的执行流程和状态;2、断点调试,可以在代码中设置断点,以便在特定位置暂停代码的执行,观察变量的值和执行流程等。

348

2023.09.19

JavaScript 全栈开发基础(Node.js + 前端)
JavaScript 全栈开发基础(Node.js + 前端)

本专题系统介绍 JavaScript 在全栈开发中的核心知识结构,涵盖 Node.js 基础、Express/Koa 接口构建、前端交互设计、模块化与包管理、数据库连接、前后端数据通信与部署流程。通过完整项目示例,帮助学习者掌握从浏览器到服务器的一体化开发能力,实现真正意义上的全栈入门。

103

2025.11.26

什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

329

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

235

2023.10.07

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

514

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5306

2023.08.17

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

2

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 9.6万人学习

【web前端】Node.js快速入门
【web前端】Node.js快速入门

共16课时 | 2万人学习

Node.js-前端工程化必学
Node.js-前端工程化必学

共19课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号