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 相关文章推荐
nodejs教程之异步I/O
Nov 21 NodeJs
nodejs事件的监听与触发的理解分析
Feb 12 NodeJs
初识NodeJS服务端开发入门(Express+MySQL)
Apr 07 NodeJs
nodejs 终端打印进度条实例代码
Apr 22 NodeJs
NodeJs使用Mysql模块实现事务处理实例
May 31 NodeJs
nodejs中sleep功能实现暂停几秒的方法
Jul 12 NodeJs
使用vs code开发Nodejs程序的使用方法
Sep 21 NodeJs
Nodejs调用WebService的示例代码
Sep 29 NodeJs
NodeJS实现视频转码的示例代码
Nov 18 NodeJs
Nodejs调用Dll模块的方法
Sep 17 NodeJs
nodejs更新package.json中的dependencies依赖到最新版本的方法
Oct 10 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
层叠菜单的动态生成
2006/10/09 PHP
手把手教你使用DedeCms的采集的图文教程
2007/03/11 PHP
PHP封装CURL扩展类实例
2015/07/28 PHP
PHP正则表达式之捕获组与非捕获组
2015/11/06 PHP
thinkphp Apache配置重启Apache1 restart 出错解决办法
2017/02/15 PHP
jquery操作select option 的代码小结
2011/06/21 Javascript
Node.js:Windows7下搭建的Node.js服务(来玩玩服务器端的javascript吧,这可不是前端js插件)
2011/06/27 Javascript
JavaScript使用RegExp进行正则匹配的方法
2015/07/11 Javascript
BootStrap初学者对弹出框和进度条的使用感觉
2016/06/27 Javascript
jQuery学习笔记之入门
2016/12/14 Javascript
xmlplus组件设计系列之图标(ICON)(1)
2017/05/05 Javascript
angularJS利用ng-repeat遍历二维数组的实例代码
2017/06/03 Javascript
Angular.js自动化测试之protractor详解
2017/07/07 Javascript
EasyUI的DataGrid绑定Json数据源的示例代码
2017/12/16 Javascript
关于微信小程序登录的那些事
2019/01/08 Javascript
详解基于node.js的脚手架工具开发经历
2019/01/28 Javascript
spring+angular实现导出excel的实现代码
2019/02/27 Javascript
vue图片上传组件使用详解
2019/12/23 Javascript
JavaScript复制变量三种方法实例详解
2020/01/09 Javascript
JavaScript语句错误throw、try及catch实例解析
2020/08/18 Javascript
[00:17]游戏风云独家报道:DD赛后说出数字秘密 吓死你们啊!
2014/07/13 DOTA
利用Python自动监控网站并发送邮件告警的方法
2016/08/24 Python
Python之日期与时间处理模块(date和datetime)
2017/02/16 Python
对Python的交互模式和直接运行.py文件的区别详解
2019/06/29 Python
opencv转换颜色空间更改图片背景
2019/08/20 Python
Python基于wordcloud及jieba实现中国地图词云图
2020/06/09 Python
中国专业的综合网上购物商城:京东
2016/08/02 全球购物
斯凯奇美国官网:SKECHERS美国
2016/08/20 全球购物
数以千计的折扣工业产品:ESE Direct
2018/05/20 全球购物
2014年党员发展工作总结
2014/12/02 职场文书
大学生党课感想
2015/08/11 职场文书
Python使用Kubernetes API访问集群
2021/05/30 Python
Java生成读取条形码和二维码的简单示例
2021/07/09 Java/Android
uniapp 微信小程序 自定义tabBar 导航
2022/04/22 Javascript
SQL Server中搜索特定的对象
2022/05/25 SQL Server
TaiShan 200服务器安装Ubuntu 18.04的图文教程
2022/06/28 Servers