千家信息网

Node.js中断路器机制是怎么样的

发表于:2024-10-14 作者:千家信息网编辑
千家信息网最后更新 2024年10月14日,这篇文章将为大家详细讲解有关Node.js中断路器机制是怎么样的,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。架构演变带来的问题当我们使用传统的 CS 架构时,服务
千家信息网最后更新 2024年10月14日Node.js中断路器机制是怎么样的

这篇文章将为大家详细讲解有关Node.js中断路器机制是怎么样的,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

架构演变带来的问题

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

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

解决问题的几种方式

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

  • 隔离模式:将不同的资源或者服务的调用分割成几个不同的请求池,一个池子的资源被耗尽并不会影响其它资源的请求,防止某个单点的故障消耗完全部的资源。这是非常传统的一种容灾设计。

  • 限流模式:熔断和隔离都是一种事后处置的方式,限流模式则可以在问题出现之前降低问题出现的概率。限流模式可以对某些服务的请求设置一个最高的 QPS 阈值,超出阈值的请求直接返回,不再占用资源处理。但是限流模式,并不能解决服务血崩的问题,因为往往引起血崩并不是因为请求的数量大,而是因为多个级联层数的放大。

断路器的机制和实现

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

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

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

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

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

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

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

断路器的状态图如下:

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

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

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

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

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

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 。对于分布式系统来说,使用这个库可以极大提升你的服务的容错能力,从根本上解决服务血崩的问题。

关于"Node.js中断路器机制是怎么样的"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

断路器 服务 资源 状态 模式 问题 阈值 故障 消耗 机制 时间 更多 用户 篇文章 不同 成熟 传统 功能 情况 方式 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全哪个部门最好 服务器工业级固态硬盘有多大 360全球最大的数据库维护 网络安全央行预警 外国服务器需要icp证明吗 青浦区新能源软件开发厂家价格 服务器在国外的app能打开吗 合肥工无忧互联网科技有限么司 启飞网络安全黑板报 大田县网络安全 改数据库键值 腾讯和平精英怎么一键换服务器 2019年网络安全人才奖 义乌云软件开发总结 魔兽世界玛诺加尔服务器为什么关了 河南ctf网络安全竞赛官网 2016重庆楼盘销售数据库 如何搭建服务器出租空间 怎么把线条导入地理空间数据库 深圳交行软件开发中心难进吗 车载网络安全架构 全景封锁数据库 keep服务器什么时候修好 方正软件开发项目管理 mysql数据库及应用 徐人凤 超哥网络技术传媒 大学信息与网络技术基础书 餐饮业用什么软件开发票 江门卫星软件开发费用 哈尔滨网络安全类公司
0