淘先锋技术网

首页 1 2 3 4 5 6 7

在看 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。

数据结构与调用关系

从上至下各层的数据结构有:

  1. Nodejs - 链表,最小堆(实现的优先队列)
  2. Libuv - 最小堆
  3. Linux - 分桶-链表,红黑树

考虑一下场景,三者之间的数据模型是怎样的

一图胜千言(点击放大)

81fb1c3992d376017d81edec97169110.png

关键函数:

  1. scheduleTimer- node 调用此函数构建了libuv的数据
  2. processTimers - node 定时器的回调函数libuv 到时会触发次回调,由此可见具体的fn[x]并没有传递而libuv,而是在node端执行的
  3. epoll_wait - libuv 调用linux系统函数构建了高精度定时器的红黑树

关键点:

  1. 三个层面的数据并不一样
    1. Node端时间+函数,三个时间点,6个函数
    2. Libuv端时间,三个时间点
    3. Linux端最小时间,一个时间点
  2. 调用关系
    1. Nodejs 把固定定时回调函数processTimers传递给libuv并通过scheduleTimer调用libuv,等待回调
    2. Libuv 读取最小时间同步阻塞调用Linux的epoll_wait,进程进入可中断睡眠等待中断
    3. Linux 高精度定时器设置APIC的cycles,继续执行其他任务,APIC到时触发中断

Nodejs 的 timers们

Nodejs 提供的timers们,除了给用户使用,其实自身也在大量使用。对于Node来说,timer应该算是一种保护机制,先看下Node自身哪里在用吧。

  1. TCP 相关模块 - http[s],net
    1. server.timeout
    2. server.keepAliveTimeout
  2. child_process 模块
    1. child_process.exec(..., {timeout})
  3. dns 模块
    1. Resolver({ timeout })
  4. readline 模块
    1. readline.createInterface({..., escapeCodeTimeout})
  5. vm 模块
    1. script.runInContext(..., { timeout})

以上模块或模块中的方法都是系统资源的重度消耗者,而nodejs 作为server端的编程语言,需要特别留意资源的开销,所以在有资源开销地方一般都会Timer守护者,以便及时的释放资源

server.timeout

本次关于定时器的主题,来自网上关于socket hang upconnect ECONNREFUSED的讨论,至此还没有涉及这方面内容。此内容将会涉及到timer以外的,socket, tcp等层面的内容,该内容相对独立,所以会作为定时器最后一节,放到下次讨论。