mysql并发 node_nodejs高并发大流量的控制并发的三种方法

nodejs高并发大流量的控制并发的三种方法

eventproxy、async.mapLimit、async.queue控制并发。

node.js优缺点:

优点: 高并发,io密集型处理, 可以作为单页面应用,便于爬虫抓取。

缺点:不适合cpu计算密集型, 对关系数据库支持不好

libuv原理:

c语言编写的基础库实现主循环,文件,网络即可

libuv的改进:

回传上下文信息,其它线程不能访问缺省主循环,loop不支持多线程

代码可读性维护改进:

async:

async.waterfall([getcatalog, getaticle,getTigle])

promise 的方法

koa写法

es6写法使用yield

var titles = []

co(function *() {

var catalog = yield getCatalog(gid)

var articles = yield getArticles(catalog)

titles = yield getTitles(articles)

});

0

1

2

3

4

5

vartitles=[]

co(function*(){

varcatalog=yieldgetCatalog(gid)

vararticles=yieldgetArticles(catalog)

titles=yieldgetTitles(articles)

});

用eventproxy、async.mapLimit、async.queue控制并发

1.用eventproxy实现控制并发

var EventProxy = require('eventproxy');

const most = 5;//并发数5

var urllist = [....];//待抓取url列表,100个

function foo(start){

var ep = new EventProxy();

ep.after('ok',most,function(){

foo(start+most);//一个批次任务完成,递归进行下一批任务

});

var q=0;

for(var i=start;i

if(q>=most){

break;//最多添加most个任务

}

http.get(urllist[i],function(res){

//....

res.on('end',function(){

ep.emit('ok');//一个任务完成,触发一次ok事件

});

});

q++;

}

}

foo(0);

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

1.用eventproxy实现控制并发

varEventProxy=require('eventproxy');

constmost=5;//并发数5

varurllist=[....];//待抓取url列表,100个

functionfoo(start){

varep=newEventProxy();

ep.after('ok',most,function(){

foo(start+most);//一个批次任务完成,递归进行下一批任务

});

varq=0;

for(vari=start;i

if(q>=most){

break;//最多添加most个任务

}

http.get(urllist[i],function(res){

//....

res.on('end',function(){

ep.emit('ok');//一个任务完成,触发一次ok事件

});

});

q++;

}

}

foo(0);

2.使用 async.mapLimit 控制并发

var async = require('async');

//模拟一组连接地址

var urls = [];

for(var i = 0; i < 30; i++) {

urls.push('http://datasource_' + i);

}

console.log(urls);

// 并发连接数的计数器

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);

};

//使用 async.mapLimit 来 5 个并发抓取,并获取结果

async.mapLimit(urls, 5, function (url, callback) {

fetchUrl(url, callback);

}, function (err, result) {

//所有连接抓取成功,返回回调结果列表

console.log('final:');

console.log(result);

});

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

varasync=require('async');

//模拟一组连接地址

varurls=[];

for(vari=0;i<30;i++){

urls.push('http://datasource_'+i);

}

console.log(urls);

// 并发连接数的计数器

varconcurrencyCount=0;

// 并发抓取数据的过程

varfetchUrl=function(url,callback){

// delay 的值在 2000 以内,是个随机的整数

vardelay=parseInt((Math.random()*10000000)%2000,10);

concurrencyCount++;

console.log('现在的并发数是',concurrencyCount,',正在抓取的是',url,',耗时'+delay+'毫秒');

setTimeout(function(){

concurrencyCount--;

//抓取成功,调用回调函数

callback(null,url+' html content');

},delay);

};

//使用 async.mapLimit 来 5 个并发抓取,并获取结果

async.mapLimit(urls,5,function(url,callback){

fetchUrl(url,callback);

},function(err,result){

//所有连接抓取成功,返回回调结果列表

console.log('final:');

console.log(result);

});

3.使用async.queue 控制并发

"use strict"

var http = require('http');

var cheerio = require('cheerio');

var URL = require('url');

var path = require('path');

var fs = require('fs');

var async = require('async');

var baseUrl = "http://cnodejs.org/";

var targetUrl = "http://cnodejs.org/";

var stime = new Date();

function sGet(url,callback){

var chunks = [];

http.get(url,(res)=>{

if (res.statusCode != '200') {

callback({message:"抓取失败,状态码:"+res.statusCode,url:url});

return;

}

res.on('data',(chunk)=>{

chunks.push(chunk);

});

res.on('end',()=>{

callback(null,Buffer.concat(chunks).toString());

});

}).on('error',(e)=>{

callback({message:"抓取失败",url:url,err:e});

});

}

sGet(targetUrl,(err,data)=>{

if (err) {

console.log(err);

return false;

}

var $ = cheerio.load(data);

var anchors = $("#topic_list a.topic_title");

console.log('共'+anchors.length+'个任务');

const most=5;//并发数

//创建队列并指定并发数

var q=async.queue(function(url,callback){

var filename = path.basename(url)+'.txt';

sGet(url, (err, data)=> {

if (err) {

callback(err);

return false;

}

fs.writeFile('./html/' + filename, data, function (err) {

if (err) {

throw err;

}

callback(null,filename);

});

});

},most);

q.drain = function() {

console.log('任务全部完成,共耗时:'+(new Date()-stime)+'ms');

}

anchors.each(function(){

var url = URL.resolve(baseUrl,$(this).attr('href'));

q.push(url,function(err,filename){

if (err) {

console.log(err);

return;

}

console.log("finished:"+filename);

});

});

});

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

"use strict"

varhttp=require('http');

varcheerio=require('cheerio');

varURL=require('url');

varpath=require('path');

varfs=require('fs');

varasync=require('async');

varbaseUrl="http://cnodejs.org/";

vartargetUrl="http://cnodejs.org/";

varstime=newDate();

functionsGet(url,callback){

varchunks=[];

http.get(url,(res)=>{

if(res.statusCode!='200'){

callback({message:"抓取失败,状态码:"+res.statusCode,url:url});

return;

}

res.on('data',(chunk)=>{

chunks.push(chunk);

});

res.on('end',()=>{

callback(null,Buffer.concat(chunks).toString());

});

}).on('error',(e)=>{

callback({message:"抓取失败",url:url,err:e});

});

}

sGet(targetUrl,(err,data)=>{

if(err){

console.log(err);

returnfalse;

}

var$=cheerio.load(data);

varanchors=$("#topic_list a.topic_title");

console.log('共'+anchors.length+'个任务');

constmost=5;//并发数

//创建队列并指定并发数

varq=async.queue(function(url,callback){

varfilename=path.basename(url)+'.txt';

sGet(url,(err,data)=>{

if(err){

callback(err);

returnfalse;

}

fs.writeFile('./html/'+filename,data,function(err){

if(err){

throwerr;

}

callback(null,filename);

});

});

},most);

q.drain=function(){

console.log('任务全部完成,共耗时:'+(newDate()-stime)+'ms');

}

anchors.each(function(){

varurl=URL.resolve(baseUrl,$(this).attr('href'));

q.push(url,function(err,filename){

if(err){

console.log(err);

return;

}

console.log("finished:"+filename);

});

});

});

你可能感兴趣的:(mysql并发,node)