Skip to content

nodejs异步浅析 #1

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的工作原理,当然很多细节没有涉及,如果感兴趣的话,大家可以研究下源码。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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