运行1000个请求,以便一次只运行10个

时间:2016-08-25 09:33:22

标签: javascript node.js asynchronous promise

对于node.js,我想http.get一些远程网址,一次只能运行10个(或n个)。

我还想在本地发生异常(m次)时重试请求,但是当状态代码返回错误(5XX,4XX等)时,请求计为有效。

这对我来说真的很难理解。

问题:

  1. 无法尝试捕获http.get,因为它是异步。
  2. 需要一种方法来重试失败请求。
  3. 我需要某种信号量来跟踪当前活动的请求数。
  4. 当所有请求完成后,我想在列表中获取所有请求URL和响应状态代码的列表,我想要排序/分组/操作,所以我需要等待所有请求完成。
  5. 似乎建议使用promises的每个异步问题,但我最终嵌套了太多的承诺,很快就变得无法修复。

2 个答案:

答案 0 :(得分:4)

有很多方法可以同时处理10个请求。

  1. 异步库 - 将异步库与.parallelLimit() method一起使用,您可以在其中指定一次要运行的请求数。

  2. 蓝鸟承诺库 - 使用Bluebird promise libraryrequest库将http.get()包装成可以返回承诺然后使用的内容Promise.map()并发选项设置为10

  3. 手动编码 - 手动编码您的请求以启动10,然后每次完成,启动另一个。

  4. 在所有情况下,您都必须手动编写一些重试代码,并且与所有重试代码一样,您必须非常仔细地确定您重试的错误类型,重试时间,重试次数之间的退避量。当你最终放弃时(所有你没有指定的东西)。

    其他相关答案:

    How to make millions of parallel http requests from nodejs app?

    Million requests, 10 at a time - manually coded example

    我首选的方法是Bluebird和promises。包括按顺序重试和结果收集,可能看起来像这样:

    const request = require('request');
    const Promise = require('bluebird');
    const get = Promise.promisify(request.get);
    
    let remoteUrls = [...];    // large array of URLs
    
    const maxRetryCnt = 3;
    const retryDelay = 500;
    
    Promise.map(remoteUrls, function(url) {
        let retryCnt = 0;
        function run() {
            return get(url).then(function(result) {
                // do whatever you want with the result here
                return result;
            }).catch(function(err) {
                // decide what your retry strategy is here
                // catch all errors here so other URLs continue to execute
                if (err is of retry type && retryCnt < maxRetryCnt) {
                    ++retryCnt;
                    // try again after a short delay
                    // chain onto previous promise so Promise.map() is still
                    // respecting our concurrency value
                    return Promise.delay(retryDelay).then(run);
                }
                // make value be null if no retries succeeded
                return null;
            });
        }
        return run();
    }, {concurrency: 10}).then(function(allResults) {
         // everything done here and allResults contains results with null for err URLs
    });
    

答案 1 :(得分:1)

简单的方法是使用async库,它有一个.parallelLimit方法,可以完全满足您的需求。