node.js 中的非阻塞/异步

luoyjx · 2016-07-09 17:43 · 771次阅读

libuv

提供异步功能的 C 库。它在运行时负责一个事件循环(Event Loop)、一个线程池、文件系统 I/O、DNS 相关和网络 I/O,以及一些其他重要功能。

非阻塞/异步

当一项请求发来,应用程序会处理这个请求,其他操作需要等这个请求处理完成才能执行。这个流程的问题是:当大量请求并发时每个请求都需要等待前一个完成,也就是说每个请求都会阻塞后面的所有请求,最糟糕的是如果前一个请求花了很长时间(比如从数据库读取 3GB 的数据)后面所有请求都跟着悲剧了。解决办法可以是引入多处理器和(或)多线程架构,这些办法各有优劣。Node.js 采用了另一种方式,不再为每个请求开启一个新的线程,而是所有请求都在单一的主线程中处理,也只做这么一件事情:处理请求——请求中包含的 I/O 操作如文件系统访问、数据库读写等,都会转发给由 libuv 管理的工作线程去执行。也就是说,请求中的 I/O 操作是异步处理的,而非在主线程上进行。这个办法就使得主线程从不会阻塞,因为所有耗时的任务都分配到了别处。你需要面对的只有唯一的主线程,所有 libuv 管理的工作线程都与你隔离开来,无需操心,Node.js 会处理好那部分。在这个架构之上重 I/O 操作变得格外高效,那些重 CPU、重内存的也一样。Node.js 提供了开箱即用的异步 I/O 调度,还有一些针对重 CPU 执行的处理,不过这已经超出本文话题范畴了。

事件驱动

基本上,所有现代系统都是主程序启动完毕之后,对每个收到的请求开启一个进程,接下来根据不同技术有不同的处理方式,有时差异会大相径庭。典型的实现是:针对一个请求开启一个线程,一步接一步执行任务操作,如果某个操作执行缓慢,这个线程上的后续操作都会随之挂起,直到所有操作完成,返回结果。而在 Node.js 中,所有的操作都注册为一个事件,等待主程序或者外部请求来触发。

收藏

暂无评论

登录后可以进行评论。没有账号?马上注册