国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

淺談Koa服務限流方法實踐

2024-05-06 15:25:18
字體:
來源:轉載
供稿:網友

最近接了一個需求,很簡單,就是起一個server,收到請求時調用某個提供好的接口,然后把結果返回。因為這個接口的性能問題,同時在請求的不能超過特定數目,要在服務中進行限流。

限流的要求是,限制同時執行的數目,超出這個數目后要在一個隊列中進行緩存。

koa 中間件不調用 next

最初的想法是在 koa 中間件中進行計數,超過6個時將next函數緩存下來。等正在進行中的任務結束時,調用next繼續其他請求。

之后發現 koa 中間件中,不執行next函數請求并不會停下,而是不再調用之后的中間件,直接返回內容。

const Koa = require('koa');const app = new Koa();app.use((ctx, next) => { console.log('middleware 1'); setTimeout(() => {  next(); }, 3000); ctx.body = 'hello';});app.use((ctx, next) => { console.log('middleware 2');});app.listen(8989);

以上代碼首先在控制臺打出 ‘middleware 1' => 瀏覽器收到 ‘hello' => 控制臺打出 ‘middleware 2'。

這里還有一個要注意的地方,就是一個請求已經結束(finish)后,他的next方法還是可以繼續調用,之后的middleware還是繼續運行的(但是對ctx的修改不會生效,因為請求已經返回了)。同樣,關閉的請求(close)也是同樣的表現。

使用 await 讓請求進行等待

延遲next函數執行不能達到目的。接下來自然想到的就是使用await讓當前請求等待。await的函數返回一個Promise,我們將這個Promise中的resolve函數存儲到隊列中,延遲調用。

const Koa = require('koa');const app = new Koa();const queue = [];app.use(async (ctx, next) => { setTimeout(() => {  queue.shift()(); }, 3000); await delay(); ctx.body = 'hello';});function delay() { return new Promise((resolve, reject) => {  queue.push(resolve); });}app.listen(8989);

上面這段代碼,在delay函數中返回一個Promise,Promise的resolve函數存入隊列中。設置定時3s后執行隊列中的resolve函數,使請求繼續執行。

針對路由進行限流,還是針對請求進行限流?

限流的基本原理實現后,下面一個問題就是限流代碼該寫在哪里?基本上,有兩個位置:

針對接口進行限流

由于我們的需求中,限流是因為要請求接口的性能有限。所以我們可以單獨針對這個請求進行限流:

async function requestSomeApi() { // 如果已經超過了最大并發 if (counter > maxAllowedRequest) {  await delay(); } counter++; const result = await request('http://some.api'); counter--; queue.shift()(); return result;}

下面還有一個方便復用的版本。

async function limitWrapper(func, maxAllowedRequest) { const queue = []; const counter = 0; return async function () {  if (counter > maxAllowedRequest) {   await new Promise((resolve, reject) => {    queue.push(resolve);   });  }  counter++;  const result = await func();  counter--;  queue.shift()();  return result; }}            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 礼泉县| 萨嘎县| 广平县| 射洪县| 桐庐县| 安塞县| 深水埗区| 镇平县| 奎屯市| 南开区| 清水河县| 厦门市| 南汇区| 瑞安市| 惠水县| 柳江县| 潼南县| 洛隆县| 张家界市| 鹤岗市| 当阳市| 若羌县| 濮阳市| 吴忠市| 石家庄市| 阳信县| 临沧市| 左贡县| 忻城县| 陇南市| 凤城市| 温泉县| 雷州市| 驻马店市| 鲁山县| 聂荣县| 潞西市| 抚顺县| 全州县| 余江县| 醴陵市|