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);
});
});
});
nodejs高并发大流量的设计实现,控制并发的三种方法的更多相关文章
- 高并发大流量专题---11、Web服务器的负载均衡
高并发大流量专题---11.Web服务器的负载均衡 一.总结 一句话总结: 推荐使用nginx七层(应用层)负载均衡的实现:配置那是相当的简单 http{ upstream cluster{ serv ...
- 高并发大流量专题---10、MySQL数据库层的优化
高并发大流量专题---10.MySQL数据库层的优化 一.总结 一句话总结: mysql先考虑做分布式缓存,过了缓存后就做mysql数据库层面的优化 1.mysql数据库层的优化的前面一层是什么? 数 ...
- 高并发大流量专题---5、CDN加速
高并发大流量专题---5.CDN加速 一.总结 一句话总结: CDN就是多整几台节点服务器,选距离用户最近的服务器来给用户服务,实现的话可以用阿里云.腾讯云他们提供的功能,简单方便,妈妈再也不用担心我 ...
- 高并发大流量专题---3、前端优化(减少HTTP请求次数)
高并发大流量专题---3.前端优化(减少HTTP请求次数) 一.总结 一句话总结: 图片地图:使用<map><area></area></map>标签. ...
- [原创]lvs+ospf+nginx实现高可用大流量web架构
lvs+ospf+nginx实现高可用大流量web架构配置总概述 架构图: 配置如下: .quagga之zebra配置: # cat /etc/quagga/zebra.conf ! ! Zebra ...
- java 分次读取大文件的三种方法
1. java 读取大文件的困难 java 读取文件的一般操作是将文件数据全部读取到内存中,然后再对数据进行操作.例如 Path path = Paths.get("file path&qu ...
- Java并发编程(二)创建线程的三种方法
进程与线程 1. 进程 进程和代码之间的关系就像音乐和乐谱之间的关系一样,演奏结束的时候音乐就不存在了但乐谱还在:程序执行结束的时候进程就消失了但代码还在,而计算机就是代码的演奏家. 2. 线程 线 ...
- php解决与处理网站高并发 大流量访问的方法
方法/步骤 首先,确认服务器硬件是否足够支持当前的流量 普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 那么必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么 ...
- 高并发下用pdo,文件排它锁,redis三种方法对比
<?php header('content-type:text/html;charset=utf-8'); // //无控制 // $DB_DSN = ' ...
随机推荐
- 最新版本sublime text3注册码
TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA12C0 A37081C5 D03164 ...
- PCB画板总结
最近几天完成了第一个PCB电路板.虽然器件不是很多,手动布线了4次才达到自己理想的效果. 但是还是有很多细节只有亲自拿到了自己做的板子,亲自焊接之后,才知道自己哪里不合适. 这是修改了4次之后的最终的 ...
- 添加ll命令
$ vim ~/.bashrcalias ll='ls -l' #加入此行 ps:加入后肯能无法当场起作用,执行该句: source ~/.bashrc
- 微信小程序中显示与隐藏(hidden)
1.wx.wxml页面部分 <view bindtap='click'>点击</view> //这是显示隐藏的部分 <view hidden="{{hidden ...
- php 判断手机号 和 手机号中间四位以**** 代替
代码: //自定义函数手机号隐藏中间四位 function get_phone($str){ $str=$str; $resstr=substr_replace($str,'****',3,4); r ...
- java web应用连接mysql会突然connection连接失败
tomcat6.0 mysql5.1 项目:java web项目 问题:原本项目运行了好几天了,一直没发现问题,突然今天报数据库连接异常,进入看日志发现 ### Error querying data ...
- pytorch入门与实践-2.2
Tensor 1--本质上可以理解为具有不同维度的数组 2--支持的基本运算 |---创建Tensor: x=t.tensor(x,y) x,y 表示数组的大小 , x=t.rand(x,y), x ...
- TensorRT层和每个层支持的精度模式
下表列出了TensorRT层和每个层支持的精确模式.它还列出了该层在深度学习加速器(DLA)上运行的能力.有关附加约束的更多信息,请参见 DLA Supported Layershttps://doc ...
- linux终端提示符显示bash-4.2#
原因是root在/root下面的几个配置文件丢失,丢失文件如下: 1..bash_profile 2..bashrc 以上这些文件是每个用户都必备的文件. 使用以下命令从主默认文件重新拷贝一份配置信息 ...
- npm笔记
#执行npm start时是运行的哪个js文件? 打开package.json看看scripts属性中start配置的是什么运行脚本,这里配置的就是你执行npm start时跑的脚本 #设置npm的源 ...