express - 一次限制一个请求

express - Limit a request to one at a time

我正在使用 express 构建一个应该在内部使用的 API。其中一个请求在服务器上触发了一个繁重的进程,应该 return 从中得到一个 CSV。此过程可能需要 10 多分钟。

为了不让服务器超载,我想限制对这个 API 的调用,因为进程没有终止,我们不能再次请求相同的 URL .

为此,我尝试使用具有以下配置的 express-rate-limit

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 分钟后到达 'max request',即使我只开始一次。我怀疑如果没有得到任何答复,浏览器会在 2 分钟后重试请求,这可能吗?

我希望此请求没有任何 retry-strategy 并且达到 max request 的唯一方法是手动要求服务器连续执行此请求 2 次。

谢谢。


编辑

这是我的完整代码:

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

TLDR:我添加了 request.connection.setTimeout(1000 * 60 * 30); 以避免每 2 分钟触发一次请求。

但考虑到我在问题中编写的代码,@Paul 的建议仍然值得考虑。