前言
今天会统整这 10 多天关於 Node 框架的探索内容。
正文
- Node 的非同步, 本质是对 AIO 机制的活用, 其中 linux 使用的 AIO 机制是 epoll , windows 用的则是 IOCP。
- Node 可以粗略分成
- JS 层 : 开发者撰写程序的地方
- C++层 : 负责连结 JS 层及 libuv 层
- libuv 层 : 利用 AIO 机制完成 schedule 和 事件执行
- Node 的起点是 C++ 层, 他会在设定完基本环境後, 向上调用 V8 运行 JS 层, 向下调用 uv_run() 运行 libuv 层
- Node 在 JS 运行 IO 事件的本质是调用藉由 V8 分享的 C++ 层方法, 使用 IOCP / epoll 等方法注册事件。所以平常 Node 运行一段具有 IO 功能的程序码, 注册完就会继续往下一行运行了。
- uv_run 在 Node 创建之初就会开始运行, 其会不断重复几个阶段 (以 IOCP 流程为主)
- libuv 开始循环
- timer stage : 检查 time heap 中有没有逾时的定时任务, 有就执行
- pending stage : 检查 pending queue 中有没有任务, 有就依照类别执行特定处理与 callback function
- polling stage : 利用 IOCP 抓取新发生的事件, 并且存入 pending queue
- endgame stage : pending 做完的事件会被推进 endgame queue , 在 endgame 阶段关闭。
- 回到 timer stage
- time heap 是一个由 libuv 维护的最小树, 需要定期触发的任务会被注册到这里, timer stage 时取出结点, 藉由与当下时间比较有没有逾时, 来决定要不要执行其 callback。
- IOCP 可以在发生已经注册的事件後把事件存到 IOCP queue , 同时提供方法使 user space 取得 IOCP queue 中的事件。
- pending stage 处理抓到的事件时会根据不同的事件种类决定要做甚麽处理。
- Node 的 threadpool 没任务时会闲置, 其目的是平行於 main thread 的完成 AIO 事件。
- 以下简述 Node 中如何利用 thread pool 完成 AIO 事件 (以 IOCP 流程为主)
- C++ 层把 AIO 任务 (含 AIO 完成後的 callback) 放入 threadpool
- threadpool 完成 AIO 任务中 AIO 的部分 ( AIO 结束後的 callback 不在 TP 中执行)
- threadpool 触发 AIO 完成的事件
- libuv 的 polling stage 抓取到 AIO 完成的事件後放入 pending queue
- libuv 的 pending stage 抓到 pending queue 中的 AIO 完成事件
- 执行基本的处理後调用该 AIO 完成事件所夹带的 callback
- libuv 的 endgame stage 关闭执行完 callback 的 AIO 任务
- Node 以 libuv 来驱动 AIO , 藉以达成非同步框架。此外还配合, threadpool 来平行化部分流程。
明天进度
我明天会利用这段时间学到的知识实作一个可以运行少少几句非同步方法的程序(乞丐版非同步架构),还有聊聊这 30 天的心得, 谢谢大家看到这里
明天见 !