Node.js - 限制我发出的请求数

时间:2018-05-08 07:01:21

标签: node.js azure azure-cosmosdb async.js

我有一个Node应用程序,其中有一个Gremlin客户端:

var Gremlin = require('gremlin');

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

然后我使用它来调用CosmoDB来添加一些记录:

async.forEach(pData, function (data, innercallback) {
    if (data.type == 'Full'){
      client.execute("g.addV('test').property('id', \"" + data.$.id + "\")", {}, innercallback);
    } else {
        innercallback(null);
    }
}, outercallback);

然而,在我的Azure端,每秒有400个请求的限制,随后我收到错误:

ExceptionType : RequestRateTooLargeException
ExceptionMessage : Message: {"Errors":["Request rate is large"]}

有没有人对如何限制每秒发出的请求数量有任何想法,而无需在Azure上扩展(因为这需要更多:) :)

此外:

我尝试使用

async.forEachLimit(pData, 400, function (data, innercallback) {
    if (data.type == 'Full'){
      client.execute("g.addV('test').property('id', \"" + data.$.id + "\")", {}, innercallback);
    } else {
        innercallback(null);
    }
}, outercallback);

然而,如果继续看RangeError: Maximum call stack size exceeded如果它太高,否则如果我减少我就会得到相同的请求率太大的异常。

感谢。

2 个答案:

答案 0 :(得分:1)

  

RangeError:超出最大调用堆栈大小

可能会发生这种情况,因为在innercallback案例中同步调用了else。它应该是:

} else {
    process.nextTick(function() {
        innercallback(null)
    });
}

forEachLimit的调用看起来通常是正确的,但您需要确保在请求真正被触发(if阻止)时,innercallback不会在1秒之前调用保证一秒钟内不超过400个请求被解雇。最简单的方法是将回调执行完全延迟1秒钟:

client.execute("g.addV('test').property('id', \"" + data.$.id + "\")", {},
function(err) {
    setTimeout(function() { innercallback(err); }, 1000);
});

更准确的解决方案是计算实际请求+响应时间,setTimeout仅计算剩余时间为1秒。

作为进一步的改进,看起来你可以在做异步内容之前过滤你的pData数组以摆脱if...else,所以最终:

var pDataFull = pData.filter(function(data) => {
    return data.type == 'Full';
});

async.forEachLimit(pDataFull, 400, function (data, innercallback) {
    client.execute("g.addV('test').property('id', \"" + data.$.id + 
        "\")", {},
        function(err) {
            setTimeout(function() { innercallback(err); }, 1000);
        }
    );
}, outercallback);

答案 1 :(得分:0)

让我们先澄清一些事情。您没有400请求/秒的收集,但400 RU / s的收集。 RU代表请求单元,它们不会转换为请求。

大致是:

  • 检索1KB的文件的检索请求将花费1卢比。
  • 检索1KB的文件的修改费用为5卢比。

假设您的文档大小为1KB,则每秒只能添加80个文档。

现在我们已经完成了这项工作,听起来async.queue()可以帮助您。