这是我的问题:
我构建了一个 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);
})
将此代码保存为
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);
});