那些曾经被我们误解的异步IO
又有一周没有写博客了,这样下去会变成荒地的,所以在睡觉之前必须要发一篇,本想把angular.js 系列接下去.....但是最近的 angular.js 用到快吐血,暂时不想再提,上手是熟练了,但是感觉长进不大,项目催的太急,空闲的时间少之又少,就连这篇博客都是从看电影的时间里抽出来的,我又堕落了,阿门!
熟悉 node.js 的朋友应该不陌生它身上牛逼闪闪的几个"大字" ,什么 '单线程' , '非阻塞' ,' 异步IO' ,'事件轮询' ,'高并发' 等等.......
确实很牛,但是最近我发现之前有个错误的认识,所以在这里纠正一下,好在我的博客就是我的一个个人记事本,允许出错,也可以随时纠正,更绝的是还不让你们评论.......不服,来咬我呀^_^,哈哈哈
裹脚布到这里就改结束了,说正事.
从javascript的诞生以来,貌似和服务器端开发就很遥远,虽然之前有些前辈一直在努力,但是在node.js 出来之前谁了解javascript可以做服务器端开发,多少人知道 commonJS 规范.
所以我们从心里就认为这门语言不是语言.....(这是什么屁话) ,认为它充其量是做前端效果,一个组件,后来的一个小框架 等等.
其实,我们一直把它局限再了浏览器这个宿主里,它能发挥多大的作用,这真不是它说了算,而是要看浏览器厂商实现了哪些api支持.
因为前端javascript 对 dom 可以随意增删改查,所以命中注定它就是'单线程' ,睡觉的同学注意了,主角开始上场了. 但是你以为的它真的是javascript ,NO! 它仅仅是运行在浏览器宿主里的javascript环境,为什么要单线程? 你有没有想过多线程去同时操作一个dom的后果!
A线程在修改dom ,B 线程在删除 dom ,最后以哪个为主,所以单线程是他们命中注定.
接着我们迎来了 伟大的node.js ,从此彻底大规模开启 javascript 服务器端编程模式, 当然这还要感谢伟大的google 公司,感谢 v8 引擎,其实服务器端javascript又是运行在另外一个宿主 (V8) 之上,也实现了很多的io处理,文件,系统级别 的api ,这时我们听到 node.js 是一门单线程异步非阻塞IO的事件回调服务器端语言.所以我一直认为node.js 就是单线程.......
其实我理解的有点问题, node.js 并不是单线程语言,而是运行在单线程上的语言. 看出来有什么区别吗?
用大白话说就是:
我认为所有api处理都跑在一个线程上,因为是异步非阻塞IO ,所以大家同时请求 api ,同时拿到请求结果状态,只是没有得到业务逻辑需要拿到的数据结果(如何得到这个业务上需要的结果数据,就是node.js的事件轮询技术)
上面的理解是错误的: 正确的解读应该 node.js 是运行在单线程上的服务器端处理语言,但是使用他的 api 时,其实是跑在多个线程下, 比如 node.js 运行的主线程为 A ,主线程如果去请求 IO 操作时,会将请求交给 B 线程, 注意: B 只做IO处理或者某一类型的事件收集器,运行结果状态还是会返回给 A 线程, 甚至还有 C , D 线程一起为 A 线程服务.
其实这个多线程正是 node.js 实现异步非阻塞IO的关键所在.
node.js 运行的单线程 A 可以理解为 web服务器调用 node.js 的所有api 所在的线程.
B ,C ,D 线程可以理解为是 A 线程或者 node 本身为了实现异步IO ,非阻塞调用 ,高效利用资源 等等的手段,这几个服务线程只对 node.js 内部可见,可用.
试想下,如果真的是一个线程,我同时读取服务器文件,处理数学计算....如果是一个线程,如何异步? 这必然会造成等待.
所以 node.js 的异步实现是主线程在非阻塞的连续执行一系列 api, 而且及时拿到调用结果状态 (这个状态只是知道调用成功或者失败,并不是我们业务逻辑真正需要的结果数据 ) ,而这些 api 又会分发到其他线程去处理,得到的结果返回给主线程,主线程上的事件轮询发现有可执行的事件,便会调用其事件回调函数,从而拿到我们业务逻辑真正需要的结果数据.