您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 冶金工业 > nodejs异步_原理和缺陷
node.js异步:原理和缺陷赵成@小型笨蛋node.jsV8解析器uvlibeiolibev事件库C模块Javascript模块netbufferchild_processfile……httphttpsfsutil……主要内容异步接口的实现uv,libev,以及libeio存在的问题异步的实现方式SynchronousI/OMultiplexingselect,pselect,poll,epoll,kqueue,libev线程模拟glibcaio,libeioKernelNativeAIO,以及WindowsOverlappedI/O前者问题多多,比如仅支持O_DIRECT方式来对磁盘读写后者用于在uv中实现Windows的异步I/O在Linux下,node.js靠libev和libeio配合使用来实现异步I/O事件驱动的一个例子varnet=require('net');varserver=net.createServer(function(socket){socket.write(Echoserver\r\n);socket.pipe(socket);});server.listen(1337,127.0.0.1);staticHandleValueConnect(constArguments&){...uv_tcp_connect(...,AfterConnect);...}uvThisisthenewnetworkinglayerforNode.ItspurposeistoabstractIOCPonwindowsandlibevonUnixsystems.Weintendtoeventuallycontainallplatformdifferencesinthislibrary•libev是一个事件驱动库,提供高性能事件循环•主要用于事件驱动的网络编程•uv是node的网络实现层•*nix下uv是对libev的封装•主要目的是实现Windows版本的node什么是libev调用流程Server.listen(1337);OnConnection();TCPWrap::Listen(arguments);listener();主线程listen(tcp-fd,backlog);ev_io_set(…,fd,EV_READ);主循环返回accept(…);connection_cb();有新连接另一个例子:fs.close(fd)staticHandleValueClose(constArguments&args){intfd=args[0]-Int32Value();if(args[1]-IsFunction()){ASYNC_CALL(close,args[1],fd)}}#defineASYNC_CALL(func,callback,...)\eio_##func(After,cb_persist(callback));什么是libeioLibeioisafull-featuredasynchronousI/OlibraryforC,modelledinsimilarstyleandspiritaslibev.Featuresinclude:asynchronousread,write,open,close,stat,unlink,fdatasync,mknod,readdiretc.•libeio为C提供异步版本的POSIXAPI•主要提供文件I/O操作•异步操作通过线程实现•libeio仅依赖pthread,跨平台能力非常好•可以和仸何事件库配合使用,比如libevlibeio做了什么fs.close(fd,callback);close(fd);eio_close(fd,…,After);After();Close(arguments);callback();eio_poll();主线程新线程close结束后为什么不用libev实现异步文件操作?@爱多对于RegularFile来说,是不能够用采用poll/epoll的,即O_NOBLOCK方式对于传统文件句柄是无效的,也就是说我们的open,read,mkdir之类的RegularFile操作必定会导致阻塞BADCASEfunctiononFileB(err){fs.readFile(c);}functiononFileA(err,data){data+=blabla;fs.writeFile(b,data,onFileB);}fs.readFile(a,onFileA);调用过程主线程fs.readFilepollonFileA新线程readreadfs.readFilepollonFileB代价代码变得非常不直观每个fs.readFile都发起一个线程线程间contextswitch时代价很大如果传递的是匿名函数,那么在执行前,函数的context会一直保存在内存中回调函数执行前资源(比如说数据库连接)不会被释放BADCASE2varconn=db.connect(...);conn.query(„SELECT*FROMtable‟,function(err){...conn.close();});•conn.close();叧能在主线程中执行•conn.query();中有很多层嵌套时conn.close();将会推迟很久才执行•大量连接并发时会有很多数据库连接阻塞Solution?如果能够并行varfilename=“a”;async(function(){vardata=fs.readFileSync(filename);data+=blabla;fs.writeFileSync(b,data);fs.readFileSync(c);});console.log(“Mainthreadisinparallel”);怎样实现async?fork();if(fork()==0){/*childprocess*/...}else{/*parentprocess*/...}•fork之后的父、子进程拥有完全相同的context•子进程的运行结果通过pipe传输node-fork使用fork的问题新进程相对昂贵进程间传递javascript对象需要额外开销不能传递函数filedestriptor会被复制,如果fork前程序已经在监听端口,子进程也将会监听同一个端口,产生竞争V8引擎不允许多个线程同时使用V8的接口,所以不可能把多线程引入nodeThankyou赵成@小型笨蛋zcbenz@gmail.com
本文标题:nodejs异步_原理和缺陷
链接地址:https://www.777doc.com/doc-5948962 .html