You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js请求次数限制问题:基于Gremlin客户端操作CosmoDB

控制Gremlin客户端请求并发数的解决方案

你现在用async.forEach直接并发处理所有数据的方式,很容易一下子给Cosmos DB发起大量请求,触发限流(429错误)或者超出吞吐量限制。下面给你几个实用的解决办法:

1. 用async原生的forEachLimit控制并发

如果你已经在使用async库,直接用它的forEachLimit方法就能控制同时执行的任务数量,不需要额外装依赖。

只需要把原来的async.forEach替换成async.forEachLimit,第三个参数就是你要限制的并发数(比如设为5,具体数值可以根据你的Cosmos DB RU吞吐量调整):

var Gremlin = require('gremlin');
const async = require('async');

const client = Gremlin.createClient(443, config.endpoint, {
    "session": false,
    "ssl": true,
    "user": `/dbs/${config.database}/colls/${config.collection}`,
    "password": config.primaryKey
});

// 替换为forEachLimit,指定并发数为5
async.forEachLimit(pData, 5, function (data, innercallback) {
    if (data.type == 'Full'){
        // 改用参数化查询,避免注入风险
        client.execute(
            "g.addV('test').property('id', idParam)",
            { idParam: data.$.id },
            function(err, results) {
                if (err) {
                    console.error(`添加记录 ${data.$.id} 失败:`, err);
                    // 想继续处理其他记录就调用innercallback();要终止批量任务就传err
                    return innercallback();
                }
                console.log(`记录 ${data.$.id} 添加成功`);
                innercallback();
            }
        );
    } else {
        // 非Full类型直接跳过
        innercallback();
    }
}, function(err) {
    if (err) {
        console.error('批量处理终止,出错:', err);
    } else {
        console.log('所有记录处理完成');
    }
});

2. 用现代Promise风格的限流库(p-limit)

如果你更习惯async/await的写法,推荐用p-limit这个轻量级库,它能更优雅地控制Promise任务的并发数。

首先安装依赖:

npm install p-limit

然后改写代码:

var Gremlin = require('gremlin');
const pLimit = require('p-limit');

const client = Gremlin.createClient(443, config.endpoint, {
    "session": false,
    "ssl": true,
    "user": `/dbs/${config.database}/colls/${config.collection}`,
    "password": config.primaryKey
});

// 限制并发数为5
const limit = pLimit(5);

// 把Gremlin的回调式调用包装成Promise
const addVertex = async (data) => {
    if (data.type !== 'Full') return;
    
    return new Promise((resolve, reject) => {
        client.execute(
            "g.addV('test').property('id', idParam)",
            { idParam: data.$.id },
            function(err, results) {
                if (err) {
                    console.error(`添加记录 ${data.$.id} 失败:`, err);
                    // 想继续处理就resolve;要终止批量任务就reject(err)
                    resolve();
                } else {
                    console.log(`记录 ${data.$.id} 添加成功`);
                    resolve();
                }
            }
        );
    });
};

// 批量执行任务
(async () => {
    try {
        // 给每个任务加上限流包装
        const tasks = pData.map(data => limit(() => addVertex(data)));
        await Promise.all(tasks);
        console.log('所有记录处理完成');
    } catch (err) {
        console.error('批量处理出错:', err);
    }
})();

重要提醒:避免查询注入风险

你原来的代码直接把data.$.id拼到Gremlin查询字符串里,存在注入风险。上面的示例已经改成参数化查询,通过{ idParam: data.$.id }传递参数,这是更安全的最佳实践。

内容的提问来源于stack exchange,提问作者userMod2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:10:44