nodejs高並發大流量的設計實現,控制並發的三種方法


nodejs高並發大流量的設計實現,控制並發的三種方法
eventproxy、async.mapLimit、async.queue控制並發
Node.js是建立在Google V8 JavaScript引擎之上的網絡服務器框架,允許開發者能夠用客戶端使用的語言JavaScript在服務器端編碼。
----------------
node.js優缺點:
優點: 高並發,io密集型處理, 可以作為單頁面應用,便於爬蟲抓取。
缺點:不適合cpu計算密集型, 對關系數據庫支持不好

nodejs高並發大流量的設計實現

原理:非阻塞事件驅動實現異步開發,通過事件驅動的I/O來操作完成跨平台數據密集型實時應用
傳統的server 每個請求生成一個線程, nodejs是一個單線程的,使用libuv保持數萬並發

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

前端優化問題:移除iscorll,合並請求,tcp優化,http優化 ,localstorate,html5離線緩存
api優化:restfulapi,標准輸入輸出
ui優化: 使用同一的框架,前端組件化
異常處理: log監控,避免大文件處理,retry處理

===================

用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<urllist.length;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);
});

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM