Skip to content

nodejs异步浅析 #1

@lucefer

Description

@lucefer

异步存在于各个编程语言中,包括nodejs,甚至nodejs将异步发挥地更加炉火纯青,而libuv则承担了nodejs异步模型的主要工作,本文将对nodejs的异步进行简要分析,

异步API

nodejs中的异步API分为I/O异步非I/O异步

  • I/O 异步

    • 网络I/O
    • 文件I/O
  • 非I/O异步

    • setTimeout、setInterval
    • setImmediate
    • process.nextTick
    • promise

I/O 异步

一、 网络I/O

libuv为了实现高效网络I/O,底层封装了各个平台的高效I/O模型。

  • windows: IOCP完成端口
  • sunos:events port
  • OSX和一些BSD系统上:kquene
  • linux系统:epoll

简单来说,nodejs 将网络 I/O 任务通过 libuv 传递给操作系统去处理,操作系统监听网络事件,一旦有了结果,就返回libuv的工作原理大致如下:

  • 1、nodejs 接收到网络I/O任务,绑定事件。
  • 2、libuv 将网络I/O下发给操作系统,绑定事件。
  • 3、操作系统监听网络 I/O 事件,当有结果返回时,操作系统内核触发事件,并通知给 libuv。
  • 4、libuv 监听到事件通知,在event-loop中执行该事件的回调函数。

至此,一个异步网络 I/O 任务就结束了,由于利用了各个平台上最优的 I/O 机制,所以nodejs的异步网络I/O很高效。

二、 文件 I/O

libuv在nodejs初始化的时候,还会开启一个默认4个线程的线程池,执行一些文件的I/O操作,以及一些DNS操作。我们之所以能够实现文件I/O的异步,就是利用了这个线程池。当有一个文件I/O任务到来时,nodejs将该任务放到一个队列中,等待空闲线程的到来。一旦有了空闲线程,就从队列中取出任务执行,执行完一个任务,该线程便返还到线程池中,等候下一个任务的到来。
当然,如果觉得4个线程不够用的话,可以在nodejs启动时设置环境变量* UV_THREADPOOL_SIZE*来指定线程池的大小,为了系统性能考虑,最大只能设置128个线程数。

结语

以上就是nodejs中 网络I/O和文件I/O的工作原理,当然很多细节没有涉及,如果感兴趣的话,大家可以研究下源码。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions