node事件循环(Event Loop)

"Event Loop 原理"

Posted by Mzx on May 18, 2017

Node事件循环(Event Loop)

nodeJS是如何实现异步I/O的呢?什么是事件驱动?揭开nodeJS的神秘面纱,还原‘事件’真相!

NodeJS架构

什么是nodeJS

nodeJS是一个基于Chrome V8引擎的运行时。

  • V8 : 高性能javascript引擎。
  • libuv : 提供异步功能的基于C的库。其运行时包含一个event loop,一个线程池和各种I/O组件。
  • zlib,c-aresC/C++组件:这些组件用于对系统底层的功能访问。
  • Bindings : 用于JS与原生的C/C++进行数据交互。即上面提到的C/C++组件是通过Bindings才能让JS访问到。
  • Addons : 如果你自己实现了一个C/C++库,那么JS该如何操作这个库呢?这里就需要你自己实现JSC/C++库的Bindings代码,你写的Bindings代码即C/C++ Addons
  • Node.js API : js代码

如何运行

上面分析了nodeJS都有哪些组件,那这些组件又是如何工作的呢?

step 1:

V8引擎将JS编译为机器码,然后执行,如果遇到I/O操作(网络请求,文件读写等),则将该操作所需的参数和回调方法打包成一个请求对象发给libuv

step 2:

libuv接收到该对象后将其放入线程池,如果线程池中有空闲线程可以执行该操作,则分发一个线程进行处理。处理完毕后,将得到的结果绑定到该对象上,然后将其放入修改该对象的状态为已执行完毕,然后归还线程

step 3:

Event LoopnodeJS启动时,libuv便会启动一个类似while (true) {}的无限循环,其会不停地轮询时间线程池中已经执行完毕的对象,当获取到执行完毕的对象时,便将请求对象放入到I/O观察者队列中,然后获取对象中绑定的结果和回调函数,执行回调函数并将绑定的结果作为参数传入。至此,便是一个完整的异步I/O调用流程。

事件循环(Event Loop

事件循环就是个循环,其不断检查是否有事件待处理,如果有,就处理该事件。如果没有则进入下一个循环。在每个循环中判断是否有事件需要处理是通过观察者判断的。

总结

  • 事件循环,观察者,请求对象,I/O线程池四者是一个完整异步I/O模型的必备要素。
  • V8是单线程,事件循环是单线程,但是libuv在处理I/O时是多线程的。