使用 async 控制并发

该博客介绍了如何在Node.js中使用async库控制并发连接数,以避免过多并发导致的恶意请求问题。通过一个示例展示了如何限制并发为5个,模拟抓取CNode社区首页主题并返回JSON格式的数据。文章探讨了async与eventproxy在异步流程控制中的应用场景选择,指出当需要控制并发数或使用函数式编程思维时,async更为适用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标:
新建一个 lesson5 项目,在其中编写代码。
代码的入口是 app.js,当调用 node app.js 时,它会输出 CNode(https://cnodejs.org/ ) 社区首页的所有主题的标题,链接和第一条评论,以 json 的格式。

注意:与之前不同的是,并发连接数需要控制在 5 个。

知识点:
1. 学习 async(https://github.com/caolan/async )的使用。
2. 学习使用 async 来控制并发连接数。


在上一节中的eventproxy控制并发中,代码并不完美,因为我们一次性发出了40个并发请求出去,要知道,除去CNode之外,很多网站可能会因为发出的并发数连接太多而当成是恶意请求,会将IP封掉。

在写爬虫的程序时,如果有1000个链接要去爬,那么不可能同时发出1000个并发链接出去,需要控制一下并发的数量,比如并发10个就好,然后慢慢爬完这1000个链接,用async来做这件事就很简单。

但是有一个问题是什么时候使用eventproxy,什么时候使用async?它们都是用来做异步流程控制的

一般来说当你需要去多个源(一般是小于 10 个)汇总数据的时候,用 eventproxy 方便;当你需要用到队列,需要控制并发数,或者你喜欢函数式编程思维时,使用 async。大部分场景是前者,所以我个人大部分时间是用 eventproxy 的。

首先,我们伪造一个 fetchUrl(url, callback)函数,这个函数的作用就是,当你通过


    fetchUrl('http://www.baidu.com', function (err, content) {
      // do something with `content`
    });

调用它时,它会返回http://www.baidu.com的页面内容回来。
当然,我们这里的返回内容是假的,返回延时是随机的。并且在它被调用时,会告诉你它现在一共被多少个地方并发调用着。


    // 并发连接数的计数器
    var concurrencyCount = 0;
    var fetchUrl = function (url, callback) {
      // delay 的值在 2000 以内,是个随机的整数
      var delay = parseInt((Math.random() * 10000000) % 2000, 10);
      concurrencyCount++;
      console.log('现在的并发数是', concurrencyCount, ',正在抓取的是', url, ',耗时' + delay + '毫秒');
      setTimeout(function () {
    concurrencyCount--;
    callback(null, url + ' html content');
      }, delay);
    };

我们接着来伪造一组链接


    var urls = [];
    for(var i = 0; i < 30; i++) {
      urls.push('http://datasource_' + i);
    }
    console.log(urls);

生成的链接如下图所示:

接着,我们使用 async.mapLimit来并发抓取,并获取结果。


    async.mapLimit(urls, 5, function (url, callback) {
      fetchUrl(url, callback);
    }, function (err, result) {
      console.log('final:');
      console.log(result);
    });

运行输出是这样的:

可以看到,一开始,并发连接数是从1开始增长的,增长到5时,就不再增加。当其中任务完成时,再继续抓取。并发连接数控制在5个。

并发连接数解释(Simultaneous Browser Connections):
并发连接数指的是客户端向服务器发起请求,并建立了TCP连接。每秒钟服务器链接的总TCP数量,就是并发连接数。

完整代码:


    var async = require('async');

    var concurrencyCount = 0;
    var fetchUrl = function (url, callback) {
      var delay = parseInt((Math.random() * 10000000) % 2000, 10);
      concurrencyCount++;
      console.log('现在的并发数是', concurrencyCount, ',正在抓取的是', url, ',耗时' + delay + '毫秒');
      setTimeout(function () {
    concurrencyCount--;
    callback(null, url + ' html content');
      }, delay);
    };

    var urls = [];
    for(var i = 0; i < 30; i++) {
      urls.push('http://datasource_' + i);
    }

    async.mapLimit(urls, 5, function (url, callback) {
      fetchUrl(url, callback);
    }, function (err, result) {
      console.log('final:');
      console.log(result);
    });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值