在看 Node http 模块文档的时候, 才留意到
server.timeout
这个属性, 本想简单介绍一下, 但是在梳理过后发现关于timeout
有庞大的内容支撑:server.timout -> node core timers -> uv timers -> linux msleep/hrtimer -> clocksource -> tsc -> cmos rtc -> clock cycle
, 所以拆分成几部分大致做下介绍, 期望定时器系列结束之后, noder 能够大致明白:clock cycle
是如何驱动 linux 的msleep/hrtimer
;linux 的 timers 与 uv timers 的关系;node timers 与 uv timers的关系。
前面叙述了计算机中timer实现原理,libuv层如何借助epoll_wait实现timer的机制,现在讲下Nodejs应用层相关的timers。
数据结构与调用关系
从上至下各层的数据结构有:
- Nodejs - 链表,最小堆(实现的优先队列)
- Libuv - 最小堆
- Linux - 分桶-链表,红黑树
考虑一下场景,三者之间的数据模型是怎样的
关键函数:
scheduleTimer
- node 调用此函数构建了libuv的数据processTimers
- node 定时器的回调函数
,libuv 到时会触发次回调
,由此可见具体的fn[x]并没有传递而libuv
,而是在node端执行的- epoll_wait - libuv 调用linux系统函数构建了高精度定时器的红黑树
关键点:
- 三个层面的数据并不一样
- Node端
时间+函数
,三个时间点,6个函数 - Libuv端
时间
,三个时间点 - Linux端
最小时间
,一个时间点
- Node端
- 调用关系
- Nodejs 把
固定
的定时回调函数processTimers
传递给libuv并通过scheduleTimer调用libuv,等待回调
- Libuv 读取最小时间
同步阻塞
调用Linux的epoll_wait,进程进入可中断睡眠
,等待中断
- Linux 高精度定时器设置APIC的cycles,
继续执行
其他任务,APIC到时触发中断
- Nodejs 把
Nodejs 的 timers们
Nodejs 提供的timers们,除了给用户使用,其实自身也在大量使用。对于Node来说,timer应该算是一种保护机制
,先看下Node自身哪里在用吧。
TCP 相关模块
- http[s],net- server.timeout
- server.keepAliveTimeout
child_process 模块
- child_process.exec(..., {timeout})
dns 模块
- Resolver({ timeout })
readline 模块
- readline.createInterface({..., escapeCodeTimeout})
vm 模块
- script.runInContext(..., { timeout})
以上模块或模块中的方法都是系统资源的重度消耗者
,而nodejs 作为server端
的编程语言,需要特别留意资源的开销
,所以在有资源开销地方一般都会Timer守护者
,以便及时的释放资源
。
server.timeout
本次关于定时器的主题,来自网上关于socket hang up
与connect ECONNREFUSED
的讨论,至此还没有涉及这方面内容。此内容将会涉及到timer以外的,socket, tcp等层面的内容,该内容相对独立,所以会作为定时器最后一节,放到下次讨论。