函數保險絲:避免函數過熱調用

前言

在平常開發中,咱們會遇到不少這樣的場景:javascript

  1. 在搶購活動中,用戶每每會頻繁刷新接口,要給接口加上防禦,頻繁調用中止響應。
  2. 在弱網環境中,每每會實現失敗重試功能,若是失敗次數多了,頻繁的重試須要制止。
  3. 在股票市場中,當價格波動的幅度在交易時間中達到某一個限定的熔斷點時,對其暫停交易一段時間的機制。
  4. ......

這類問題,本質是:「過熱的調用」java

在物理電路中,對於「過熱的調用」有一種你們生活中都常見的電子元件:保險絲git

保險絲會在電流異常升高到必定的高度和熱度的時候,自身熔斷切斷電流,保護電路安全運行。github

咱們能夠模仿這樣的思路,去解決編程中的「過熱的調用」問題:npm

  1. 設定一個閾值,若是函數在短期內調用次數達到這個閾值,就熔斷一段時間。
  2. 在函數有一段時間沒有被調用了,讓函數的熱度降下來。

函數保險絲的功能實現

基於以上的思路,我實現了一個 npm 庫:Method Fuse編程

使用方式以下:安全

Step1:安裝

npm install @jerryc/method-fusemarkdown

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;
複製代碼
相關文章
相關標籤/搜索