关于设计模式:函数保险丝避免函数过热调用

3次阅读

共计 1686 个字符,预计需要花费 5 分钟才能阅读完成。

前言

在日常开发中,咱们会遇到很多这样的场景:

  1. 在抢购流动中,用户往往会频繁刷新接口,要给接口加上防护,频繁调用进行响应。
  2. 在弱网环境中,往往会实现失败重试性能,如果失败次数多了,频繁的重试须要禁止。
  3. 在股票市场中,当价格稳定的幅度在交易工夫中达到某一个限定的熔断点时,对其暂停交易一段时间的机制。
  4. ……

这类问题,实质是:「过热的调用」

在物理电路中,对于「过热的调用」有一种大家生存中都常见的电子元件: 保险丝

保险丝会在电流异样升高到肯定的高度和热度的时候,本身熔断切断电流,爱护电路平安运行。

咱们能够模拟这样的思路,去解决编程中的「过热的调用」问题:

  1. 设定一个阈值,如果函数在短时间内调用次数达到这个阈值,就熔断一段时间。
  2. 在函数有一段时间没有被调用了,让函数的热度降下来。

函数保险丝的性能实现

基于以上的思路,我实现了一个 npm 库:Method Fuse

应用形式如下:

Step1:装置

npm install @jerryc/method-fuse

Step2:疾速应用

import {MethodFuse} from '@jerryc/method-fuse';

// 一个申请近程资源的异步函数
const getAssets = async () => API.requestAssets();

// 创立 MethodFuse 实例
const fuse = new MethodFuse({
  // 命名,用于日志输入
  name: 'TestFuse',

  // 最大负荷,默认:3
  maxLoad: 3,

  // 每次熔断工夫。每次熔断之后,距离 N 毫秒之后重铸,默认:5000ms
  breakingTime: 5000,

  // 主动冷却工夫。在最初一次调用距离 N 毫秒之后主动重铸,默认:1000ms
  coolDownTime: 1000,
});

// 代理原函数
const getAssetsProxy = fuse.proxy(getAssets);

// 高频并发调用 getAssetsProxy。getAssetsProxy();
getAssetsProxy();
getAssetsProxy();
getAssetsProxy(); // 此次调用会熔断
setTimeout(() => getAssetsProxy(), 5000); // 期待熔断重铸后,方可从新调用。// 以上会打印日志:// [method-fuse:info] TestFuse- 通过保险丝 (1/3)
// [method-fuse:info] TestFuse- 通过保险丝 (2/3)
// [method-fuse:info] TestFuse- 通过保险丝 (3/3)
// [method-fuse:error] TestFuse- 保险丝熔断,5000ms 之后重铸
// [method-fuse:info] TestFuse- 保险丝重置
// [method-fuse:info] TestFuse- 通过保险丝 (1/3)

Step3:应用装璜器

如果你的我的项目中反对 TS 或者 ES Decorator,那么 MethodFuse 提供了快捷应用的装璜器。

import {decorator as methodFuse} from '@jerryc/method-fuse';

@methodFuse({name: 'TestFuse'})
async function getAsset() {return API.requestAssets();
};

Step4:批改日志级别

MethodFuse 内置了一个迷你 logger(power by @jerryc/mini-logger),不便外部日志打印,内部能够取得 Logger 的实例,进行 log level 的管制。

import {LoggerLevel} from '@jerryc/mini-logger';
import {logger, MethodFuse} from '@jerryc/method-fuse';

// 创立 MethodFuse 实例
const MethodFuse = new MethodFuse({name: 'TestFuse'});

// 下调 Log level
logger.level = LoggerLevel.ERROR;
正文完
 0