最近在做一个支持多进程请求的 Node 服务,要支持多并发请求,而且请求要按先后顺序串联同步执行返回结果。
对,这需求就是这么奇琶,业务场景也是那么奇琶。
需求是完成了,为了对 Node.js 高并发请求原理有更深一些的理解,特意写一篇文章来巩固一下相关的知识点。
问题
Node.js 由这些关键字组成: 事件驱动、非阻塞I/O、高效、轻量 。
于是在我们刚接触 Node.js 时,会有所疑问:
- 为什么在浏览器中运行的 JavaScript 能与操作系统进行如此底层的交互?
- Node 真的是单线程吗?
- 如果是单线程,他是如何处理高并发请求的?
- Node 事件驱动是如何实现的?
下来我们一起来解秘这是怎么一回事!
架构一览
上面的问题,都挺底层的,所以我们从 Node.js 本身入手,先来看看 Node.js 的结构。
- Node.js 标准库,这部分是由 Javascript编写的,即我们使用过程中直接能调用的 API。在源码中的 lib 目录下可以看到。
- Node bindings,这一层是 Javascript 与底层 C/C++ 能够沟通的关键,前者通过 bindings 调用后者,相互交换数据。
- 第三层是支撑 Node.js 运行的关键,由 C/C++ 实现。
- V8:Google 推出的 Javascript VM,也是 Node.js 为什么使用的是 JavaScript 的关键,它为 JavaScript 提供了在非浏览器端运行的环境,它的高效是 Node.js 之所以高效的原因之一。
- Libuv:它为 Node.js 提供了跨平台,线程池,事件池,异步 I/O 等能力,是 Node.js 如此强大的关键。
- C-ares:提供了异步处理 DNS 相关的能力。
- http_parser、OpenSSL、zlib 等:提供包括 http 解析、SSL、数据压缩等其他的能力。
单线程、异步
- 单线程:所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。Node 单线程指的是 Node 在执行程序代码时, 主线程是单线程 。
- 异步:主线程之外,还维护了一个"事件队列"(Event queue)。当用户的网络请求或者其它的异步操作到来时,Node 都会把它放到 Event Queue 之中,此时并不会立