• 首页
  • nodejs
  • 海量数据大行其道的今天 node.js 在IO方面如何异步非阻塞

海量数据大行其道的今天 node.js 在IO方面如何异步非阻塞

以其高性能,异步IO著称,当然node.js 在 stream 上的异步也非常到位. 我们一般理解的异步请求是这样的: 同时处理多件件事件 A,B,C,D,E,F,G .... 如果用.net语言去处理这些事情可能有2钟情况 (1) A,B ..... G 按照顺序一件一件处理,最后得到返回值. (2)开启多线程去同时执行多个事件. 而node是单线程处理语言,天生就不是富二代,资源还有限......上帝造物的时候是公平,当你发现关上一扇门的话,同时肯定会为你开一扇窗.所以node 有了异步回调. 所以node.js下的处理可能是这样的: A,B ...... G 依然是按照这个顺序处理,但是得到的返回值可能是先返回 G 然后得到 A 的.

那么IO操作中 stream 是如何处理的呢?

var fs = require('fs')

fs.readFile('/etc/hosts', function (err, buffer) {
  if (err) {    
    return console.error(err.stack)
  }

  console.log(buffer.toString('utf8'))
})

这种方式是读取一个文件到内存中,然后再输出到控制台,必须先全部读取文件在先,而后从内存写入到console,中间可能有等待,当然这是个非常小的文件. 上面的方法和其他同步语言处理文件貌似没有俩样,如果遇到特别大的文件,而且node.js是单进程,这样必须会堵塞啊,其实node.js 还有一种在IO操作文件上的异步. 我的cod文件夹下有个比较大的文件文件 

node.js 使用另外一种异步处理文件流的方式读取大文件.

var fs=require('fs');
var http=require('http');

var server=http.createServer(function(req,res){
	var stream=fs.createReadStream(__dirname+'/data.txt',{flags:'r'});
	stream.pipe(res);
});

server.listen(9999);

和上面的代码比较,有俩处变动,fs 用了 createReadStream  , stream.pipe 

这种方式并不是一下把整个文件读入内存,而是从文件变为读取流后有进过管道(pipe) 到 response 流中.

通俗点讲就是相当于拿了一根管子,一头是 file stream 入口,一头是 response stream 出口,有了这个管子读取再大的文件都是易如反掌.

下面我们用2个桶子来比喻:

    

如果都从顶部注水,上边的水桶必须关闭水龙头后才能执行下一步操作.

下边的水桶因为本身自带了一个小水龙头,所以不需要关闭注水水龙头也可以进行下一步操作.那么下边的水桶工作模式是异步无阻塞的.

所以上面的代码把6.7M的文件一点一点读出来再通过管道一点一点response到页面,对用户来说是不需要等待的,这种流的异步处理非常有效率.



回到顶部