问题描述
我正在使用 express
来构建API应该在内部使用.该请求之一触发了服务器上的繁重进程,应从中返回CSV.此过程可能需要10分钟以上.
I'm using express
to build a API that should be used internally. One of the request trigger an heavy process on the server and should return a CSV out of that. This process might take more than 10 minutes.
为了不使服务器超载,我想限制此API的调用并使之调用,以使该进程不会终止,因此我们无法再次请求相同的URL.
To not overloading the server I want to restrict the call of this API and make it so that, since the process isn't terminated, we can't request the same URL again.
为此,我尝试使用 express-rate-limit
具有以下配置:
For this I tried to use express-rate-limit
with the following configuration:
new RateLimit({
windowMs: 30 * 60 * 1000, // 30 minutes
max: 1,
delayMs: 0, // disabled
message: 'Their is already a running execution of the request. You must wait for it to be finished before starting a new one.',
handler: function handler(req, res) {
logger.log('max request achieved');
logger.log(res);
},
});
但是,即使我只启动一次,似乎也要在2分钟后每次都达到最大请求".我怀疑浏览器会在2分钟后重试该请求,如果没有任何答案,可以吗?
But it seems that the 'max request' is reached every time after exactly 2 mins even if I start only once. I suspect the browser to retry the request after 2 min if doesn't get any answer, is it possible?
我希望此请求没有任何 retry-strategy
,并且达到 max request
的唯一方法是通过手动要求服务器执行此操作连续请求两次.
I would like that this request doesn't have any retry-strategy
and that the only way the max request
is reached is by manually asking the server to execute this request 2 times in a row.
谢谢.
这是我的完整代码:
const app = express();
const port = process.env.API_PORT || 3000;
app.enable('trust proxy');
function haltOnTimedout(req, res, next) {
if (!req.timedout) { next(); }
}
app.use(timeout(30 * 60 * 1000)); // 30min
app.use(haltOnTimedout);
app.listen(port, () => {
logger.log(`Express server listening on port ${port}`);
});
// BILLING
const billingApiLimiter = new RateLimit({
windowMs: 30 * 60 * 1000, // 30 minutes
max: 1,
delayMs: 0, // disabled
message: 'Their is already a running execution of the request. You must wait for it to be finished before starting a new one.',
handler: function handler(req, res) {
logger.log('max request achieved');
},
});
app.use('/billing', billingApiLimiter);
app.use('/billing', BillingController);
还有我的 route
的代码:
router.get('/billableElements', async (request, response) => {
logger.log('Route [billableElements] called');
const { startDate } = request.query;
const { endDate } = request.query;
try {
const configDoc = await metadataBucket.getAsync(process.env.BILLING_CONFIG_FILE || 'CONFIG_BILLING');
const billableElements = await getBillableElements(startDate, endDate, configDoc.value);
const csv = await produceCSV(billableElements);
logger.log('csv produced');
response.status(200).send(`${csv}`);
} catch (err) {
logger.error('An error occured while getting billable elements.', err);
response.status(500).send('An internal error occured.');
}
});
推荐答案
我找到了此GitHub问题的答案谢谢: https://github.com/expressjs/express/issues/2512 .
I found the answer thank's to this GitHub issue: https://github.com/expressjs/express/issues/2512.
TLDR:我添加了 request.connection.setTimeout(1000 * 60 * 30);
以避免每2分钟触发一次请求.
TLDR: I added request.connection.setTimeout(1000 * 60 * 30);
to avoid firing the request every 2 minutes.
但是考虑到我在问题中编写的代码,@ Paul的建议仍然值得考虑.
But considering the code I wrote inside my question, @Paul's advices are still good to be taken into account.
这篇关于表达-一次将一个请求限制为一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!