如何间隔(限速)源自处理从 Webhook 收到的请求的 Express 应用程序的传出 axios 请求?

问题描述 投票:0回答:1

这是我的问题:

我构建了一个 Node Express 应用程序,用于处理来自 Webhook 的传入请求,该 Webhook 有时会在一秒钟内发送数十个包。处理请求后,我需要使用 Axios 和转换后的数据发出 API POST 请求。

不幸的是,该 API 的速率限制为每秒 2 个请求。

我正在寻找一种方法来构建某种排队系统,该系统接受每个传入请求,并以每秒 2 个请求的有限速率发送传出请求。

我尝试用 SetTimeout 添加延迟,但它只是延迟了加载 => 当收到数百个请求时,每个请求的处理都延迟了 10 秒,但它们仍然几乎同时发送出去,只是10秒后。

我正在考虑尝试记录每个传出请求的时间,并且仅在(time - timeOfLastRequest > 500ms)时发送新的传出请求,但我很确定这不是处理此问题的正确方法。

这是一个非常基本的代码版本来说明我的问题:

// API1 SOMETIMES RECEIVES DOZENS OF API CALLS PER SECOND
app.post("/api1", async (req, res) => { 

    const data = req.body.object;

    const transformedData = await transformData(data);

    // API2 ONLY ACCEPTS 2 REQUEST PER SECOND
    const resp = await sendToApi2WithAxios(transformedData); 

})
node.js express axios
1个回答
0
投票

将此代码保存为

data.js
文件 您可以将 get 呼叫替换为 post 呼叫。

import axios from 'axios';

const delay = time => new Promise(res => setTimeout(res,time));

const delayCall = async () => {
    try {
        let [seconds, nanoseconds] = process.hrtime();
        console.log('Time is: ' + (seconds + nanoseconds/1000000000) + ' secs');
        let resp = await axios.get(
            'https://worldtimeapi.org/api/timezone/Europe/Paris'
        );
        console.log(JSON.stringify(resp.data.datetime, null, 4));

        await delay(501);
        [seconds, nanoseconds] = process.hrtime();
        console.log('Time is: ' + (seconds + nanoseconds/1000000000) + ' secs');

        resp = await axios.get(
            'https://worldtimeapi.org/api/timezone/Europe/Paris'
        );
        console.log(JSON.stringify(resp.data.datetime, null, 4));
    } catch (err) {
        console.error(err);
    }
};

delayCall();

在packages.json中

{
  "dependencies": {
    "axios": "^1.2.1"
  },
  "type": "module"
}

从终端安装并运行它

npm install axios
node data.js

结果 - 它将保证 API 调用超过 501 毫秒

$ node data.js
Time is: 3074.690104402 secs
"2022-12-07T18:21:41.093291+01:00"
Time is: 3077.166384501 secs
"2022-12-07T18:21:43.411450+01:00"

所以你的代码

const delay = time => new Promise(res => setTimeout(res,time));
// API1 SOMETIMES RECEIVES DOZENS OF API CALLS PER SECOND
app.post("/api1", async (req, res) => { 
    const data = req.body.object;

    const transformedData = await transformData(data);

    await delay(501);

    // API2 ONLY ACCEPTS 2 REQUEST PER SECOND
    const resp = await sendToApi2WithAxios(transformedData); 
});
© www.soinside.com 2019 - 2024. All rights reserved.