使用 async 控制并發(fā)

《使用 async 控制并發(fā)》

目標(biāo)

建立一個(gè) lesson5 項(xiàng)目凰浮,在其中編寫(xiě)代碼。

代碼的入口是 app.js,當(dāng)調(diào)用 node app.js 時(shí)作瞄,它會(huì)輸出 CNode(https://cnodejs.org/ ) 社區(qū)首頁(yè)的所有主題的標(biāo)題,鏈接和第一條評(píng)論危纫,以 json 的格式宗挥。

注意:與上節(jié)課不同,并發(fā)連接數(shù)需要控制在 5 個(gè)种蝶。

輸出示例:

[
  {
    "title": "【公告】發(fā)招聘帖的同學(xué)留意一下這里",
    "href": "http://cnodejs.org/topic/541ed2d05e28155f24676a12",
    "comment1": "呵呵呵呵"
  },
  {
    "title": "發(fā)布一款 Sublime Text 下的 JavaScript 語(yǔ)法高亮插件",
    "href": "http://cnodejs.org/topic/54207e2efffeb6de3d61f68f",
    "comment1": "沙發(fā)契耿!"
  }
]

知識(shí)點(diǎn)

  1. 學(xué)習(xí) async(https://github.com/caolan/async ) 的使用。這里有個(gè)詳細(xì)的 async demo 演示:https://github.com/alsotang/async_demo
  2. 學(xué)習(xí)使用 async 來(lái)控制并發(fā)連接數(shù)螃征。

課程內(nèi)容

lesson4 的代碼其實(shí)是不完美的搪桂。為什么這么說(shuō),是因?yàn)樵?lesson4 中盯滚,我們一次性發(fā)了 40 個(gè)并發(fā)請(qǐng)求出去锅棕,要知道拙泽,除去 CNode 的話,別的網(wǎng)站有可能會(huì)因?yàn)槟惆l(fā)出的并發(fā)連接數(shù)太多而當(dāng)你是在惡意請(qǐng)求裸燎,把你的 IP 封掉。

我們?cè)趯?xiě)爬蟲(chóng)的時(shí)候泼疑,如果有 1000 個(gè)鏈接要去爬德绿,那么不可能同時(shí)發(fā)出 1000 個(gè)并發(fā)鏈接出去對(duì)不對(duì)?我們需要控制一下并發(fā)的數(shù)量退渗,比如并發(fā) 10 個(gè)就好移稳,然后慢慢抓完這 1000 個(gè)鏈接。

用 async 來(lái)做這件事很簡(jiǎn)單会油。

這次我們要介紹的是 async 的 mapLimit(arr, limit, iterator, callback) 接口个粱。另外,還有個(gè)常用的控制并發(fā)連接數(shù)的接口是 queue(worker, concurrency)翻翩,大家可以去 https://github.com/caolan/async#queueworker-concurrency 看看說(shuō)明都许。

這回我就不帶大家爬網(wǎng)站了,我們來(lái)專注知識(shí)點(diǎn):并發(fā)連接數(shù)控制嫂冻。

對(duì)了胶征,還有個(gè)問(wèn)題是,什么時(shí)候用 eventproxy桨仿,什么時(shí)候使用 async 呢睛低?它們不都是用來(lái)做異步流程控制的嗎?

我的答案是:

當(dāng)你需要去多個(gè)源(一般是小于 10 個(gè))匯總數(shù)據(jù)的時(shí)候服傍,用 eventproxy 方便钱雷;當(dāng)你需要用到隊(duì)列,需要控制并發(fā)數(shù)吹零,或者你喜歡函數(shù)式編程思維時(shí)罩抗,使用 async。大部分場(chǎng)景是前者瘪校,所以我個(gè)人大部分時(shí)間是用 eventproxy 的澄暮。

正題開(kāi)始。

首先阱扬,我們偽造一個(gè) fetchUrl(url, callback) 函數(shù)泣懊,這個(gè)函數(shù)的作用就是,當(dāng)你通過(guò)

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

調(diào)用它時(shí)麻惶,它會(huì)返回 http://www.baidu.com 的頁(yè)面內(nèi)容回來(lái)馍刮。

當(dāng)然,我們這里的返回內(nèi)容是假的窃蹋,返回延時(shí)是隨機(jī)的卡啰。并且在它被調(diào)用時(shí)静稻,會(huì)告訴你它現(xiàn)在一共被多少個(gè)地方并發(fā)調(diào)用著。

// 并發(fā)連接數(shù)的計(jì)數(shù)器
var concurrencyCount = 0;
var fetchUrl = function (url, callback) {
  // delay 的值在 2000 以內(nèi)匈辱,是個(gè)隨機(jī)的整數(shù)
  var delay = parseInt((Math.random() * 10000000) % 2000, 10);
  concurrencyCount++;
  console.log('現(xiàn)在的并發(fā)數(shù)是', concurrencyCount, '振湾,正在抓取的是', url, ',耗時(shí)' + delay + '毫秒');
  setTimeout(function () {
    concurrencyCount--;
    callback(null, url + ' html content');
  }, delay);
};

我們接著來(lái)偽造一組鏈接

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

這組鏈接的長(zhǎng)這樣:


1.png

接著亡脸,我們使用 async.mapLimit 來(lái)并發(fā)抓取押搪,并獲取結(jié)果。

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

運(yùn)行輸出是這樣的:


2.png

可以看到浅碾,一開(kāi)始大州,并發(fā)鏈接數(shù)是從 1 開(kāi)始增長(zhǎng)的,增長(zhǎng)到 5 時(shí)垂谢,就不再增加厦画。當(dāng)其中有任務(wù)完成時(shí),再繼續(xù)抓取滥朱。并發(fā)連接數(shù)始終控制在 5 個(gè)根暑。

完整代碼請(qǐng)參見(jiàn) app.js 文件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末焚虱,一起剝皮案震驚了整個(gè)濱河市购裙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹃栽,老刑警劉巖躏率,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異民鼓,居然都是意外死亡薇芝,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門丰嘉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)夯到,“玉大人,你說(shuō)我怎么就攤上這事饮亏∷<郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵路幸,是天一觀的道長(zhǎng)荐开。 經(jīng)常有香客問(wèn)我,道長(zhǎng)简肴,這世上最難降的妖魔是什么晃听? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上能扒,老公的妹妹穿的比我還像新娘佣渴。我一直安慰自己,他們只是感情好初斑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布辛润。 她就那樣靜靜地躺著,像睡著了一般见秤。 火紅的嫁衣襯著肌膚如雪频蛔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,166評(píng)論 1 308
  • 那天秦叛,我揣著相機(jī)與錄音,去河邊找鬼瀑粥。 笑死挣跋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狞换。 我是一名探鬼主播避咆,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼修噪!你這毒婦竟也來(lái)了查库?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤黄琼,失蹤者是張志新(化名)和其女友劉穎樊销,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體脏款,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡围苫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了撤师。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剂府。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剃盾,靈堂內(nèi)的尸體忽然破棺而出腺占,到底是詐尸還是另有隱情,我是刑警寧澤痒谴,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布衰伯,位于F島的核電站,受9級(jí)特大地震影響闰歪,放射性物質(zhì)發(fā)生泄漏嚎研。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望临扮。 院中可真熱鬧论矾,春花似錦、人聲如沸杆勇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蚜退。三九已至闰靴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钻注,已是汗流浹背蚂且。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留幅恋,地道東北人杏死。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捆交,于是被迫代替她去往敵國(guó)和親淑翼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容