nodejs中实现阻塞实例


Posted in NodeJs onMarch 24, 2015

node.js中与生俱来的单线程编程、回调函数异步式风格让我们有时喜有时忧。先说单线程,很多人会费解于node.js的单线程如何能做到高并发?这个问题不是本文重点,点到为止。澄清一点,node.js的单线程仅仅指javascript引擎是单线程的,无论如何我们没有办法在javascript中实现多线程和阻塞(本文用到的方法同样不是通过V8引擎实现同步的);但对于node.js的其他方面不代表不能多线程,例如IO。如果现在node.js遭受大量请求,而这些请求都是IO密集型的,那么此时node每接受一个请求,在遇到耗时较长的IO操作时,javascript线程并不会一直在此等待,而是交出控制,在回调堆栈里添加IO操作完成后要执行的操作(当回调层级过多,访问数量过大,大量的回调链可能会爆栈)。而在这段时间内,node.js又可以处理其他请求了。所以对于node.js而言,虽然javascript是单线程的,每次只能处理一个请求,但javascript处理一个请求的时间往往较短(对于IO密集型应用而言),只要可以异步处理,那么在处理的过程中,此次请求都会释放控制,使node.js能处理其他请求。这并发请求的同时,IO其实一直处于并发状态,减少处理请求的线程数,节约资源以增加IO的线程数,对于通常耗时很长的IO密集型请求来说,无疑能带来性能上的提升。

前面???锣碌匾恢痹谇康?O密集型,其实是在强调node.js的强项。相应的,它的短板就是CPU密集型的请求。道理很简单,javascript不会并发,只能一个请求完成后才能处理其他请求。一个请求处理的时间越长,其他请求等待的时间越长。同一时间只会有一个请求被处理,并发性能很低。

话说到这儿,我想申明一点:node.js不应该被阻塞;能异步处理的方法异步处理(如使用fs.readFile(),而非fs.syncReadFile()fs.readFileSync()方法)。

node中不能阻塞,并不代表node外不能阻塞。前面我们有讲到fibers,现在,我们就来尝试在fibers中实现阻塞。就以处理一个http请求为例吧:

var Fiber = require('fibers');

var http = require("http");

Fiber(function () {

    var httpFiber = Fiber.current;

    var html = "";

    http.get("http://www.baidu.com", function (res) {

        var dataFiber = Fiber.current;

        res.on("data", function (data) {

            html += data;

        });

        res.on("end", function (data) {

            httpFiber.run();

        });

    });

    Fiber.yield();

    console.log(html);

}).run();

yield()、 run()这两个方法还不了解的同学,请自行查阅《fibers in node》。

fibers的运行并不在node进程中,所以在fibers内部实现阻塞对node整体的性能并没有影响。而且实现起来也是相当容易,只需要在想阻塞的时候,把fiber yield掉。需要继续运行,则执行 run()恢复fiber。在上面的例子中,我们希望当http.get请求发起时阻塞当前程序,当所有数据接收完成时,恢复程序。于是我们在调用http.get后使用 Fiber.yield()中断此fiber。在对response的监听中,如果触发 end事件表明数据传输完成,于是在 end的回调函数中,调用 Fiber.current.run()恢复fiber,这样,后续的代码就以同步的方式拿到http.get请求的数据。

上面的示例只是提供一种思路。如果对这种思路进行一些抽象封装,比如说,对有接受回调函数为参数的异步方法进行一步柯里化,在调用后中断,并劫持回调函数,以恢复程序的代码为回调函数。获取异步数据后,再程序触发预定的回调函数,这样基本能实现异步方法同步化。这段说得比较乱,基本上就是 fibers/future的实现思路,如果有兴趣,请参考其源代码。

NodeJs 相关文章推荐
golang、python、php、c++、c、java、Nodejs性能对比
Mar 12 NodeJs
nodejs实用示例 缩址还原
Dec 28 NodeJs
Nodejs极简入门教程(三):进程
Oct 27 NodeJs
nodejs搭建本地http服务器教程
Mar 13 NodeJs
用nodeJS搭建本地文件服务器的几种方法小结
Mar 16 NodeJs
nodejs和C语言插入mysql数据库乱码问题的解决方法
Apr 14 NodeJs
深入理解nodejs中Express的中间件
May 19 NodeJs
NodeJs中express框架的send()方法简介
Jun 20 NodeJs
浅谈nodejs中的类定义和继承的套路
Jul 26 NodeJs
nodejs express配置自签名https服务器的方法
May 22 NodeJs
nodejs同步调用获取mysql数据时遇到的大坑
Mar 02 NodeJs
nodejs的安装使用与npm的介绍
Sep 11 NodeJs
nodejs中使用多线程编程的方法实例
Mar 24 #NodeJs
nodejs中实现sleep功能实例
Mar 24 #NodeJs
nodejs中的fiber(纤程)库详解
Mar 24 #NodeJs
nodeJS代码实现计算交社保是否合适
Mar 09 #NodeJs
Nodejs关于gzip/deflate压缩详解
Mar 04 #NodeJs
nodejs URL模块操作URL相关方法介绍
Mar 03 #NodeJs
Windows系统中安装nodejs图文教程
Feb 28 #NodeJs
You might like
IIS+PHP+MySQL+Zend配置 (视频教程)
2006/12/13 PHP
php中的注释、变量、数组、常量、函数应用介绍
2012/11/16 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
Javascript 表单之间的数据传递代码
2008/12/04 Javascript
左侧是表头的JS表格控件(自写,网上没有的)
2013/06/04 Javascript
js获取url中"?"后面的字串方法
2014/05/15 Javascript
jQuery源码分析之Callbacks详解
2015/03/13 Javascript
animate 实现滑动切换效果【实例代码】
2016/05/05 Javascript
jQuery移动端图片上传组件
2016/06/12 Javascript
angular中ui calendar的一些使用心得(推荐)
2017/11/03 Javascript
Vue组件中slot的用法
2018/01/30 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
基于NodeJS开发钉钉回调接口实现AES-CBC加解密
2020/08/20 NodeJs
[47:50]Secret vs VP 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python通过文件头判断文件类型
2015/10/30 Python
Flask框架的学习指南之制作简单blog系统
2016/11/20 Python
Python程序运行原理图文解析
2018/02/10 Python
python pandas库中DataFrame对行和列的操作实例讲解
2018/06/09 Python
详解用python实现基本的学生管理系统(文件存储版)(python3)
2019/04/25 Python
解决在pycharm运行代码,调用CMD窗口的命令运行显示乱码问题
2019/08/23 Python
python网络编程 使用UDP、TCP协议收发信息详解
2019/08/29 Python
使用python脚本自动创建pip.ini配置文件代码实例
2019/09/20 Python
浅析matlab中imadjust函数
2020/02/27 Python
如何在mac下配置python虚拟环境
2020/07/06 Python
HTML5本地存储之IndexedDB
2017/06/16 HTML / CSS
微软俄罗斯官方网站:Microsoft俄罗斯
2016/09/18 全球购物
Mytheresa英国官网:拥有160多个奢侈品品牌
2016/10/09 全球购物
中国双语服务优势的在线购票及活动平台:247tickets
2018/10/26 全球购物
中专毕业自我鉴定
2013/10/16 职场文书
医科大学生的自我评价
2013/12/04 职场文书
历史系自荐信范文
2013/12/24 职场文书
亲子运动会的活动方案
2014/08/17 职场文书
小学生作文写作技巧100例,非常实用!
2019/07/08 职场文书
感恩信:写给爸爸妈妈的一封感谢信
2019/09/12 职场文书
vue中利用mqtt服务端实现即时通讯的步骤记录
2021/07/01 Vue.js
DE1107机评
2022/04/05 无线电