zoukankan      html  css  js  c++  java
  • 对Node.JS的事件轮询(Event Loop)的理解

    当我们知道I/O操作和创建新线程的开销是巨大的!

    网站延迟的开销

    对于一个网站,后台大多不需要进行复杂的计算,我们的程序大多时间花费在I/O读取上。

    看到一个数据:IO操作可以比数据处理慢几个数量级。高端SSD固态硬盘的读取速度可以达到200mb-700mb/s;读取1000字节需要1.4微秒。而在此期间,2GHZ频率的CPU可以执行28000个指令处理周期。而网络数据的IO甚至更慢!

    image

    NodeJS采用单线程非阻塞的架构解决老大难的IO问题

    当采用多线程时,为每一个请求开启一个新的线程(Apache就是这样做的)。当并发增多,线程的消耗会十分严重。

    什么是阻塞和非阻塞呢?

    阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
    非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

    var fs = require("fs");
    fs.readFile("./testfile", "utf8", function(error, file) {  
         if (error) throw error;  
         console.log("我读完文件了!");
    });
    console.log("我不会被阻塞!");
    

    用node执行以下代码,会先输出我不会被阻塞,再输出我读完文件了

    一个知乎的回答:

    你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。

    NodeJS的事件轮询

    这是node虽然为单线程,但是可以处理大并发,高吞吐量的核心。一个事件轮询拥有下面三个组件

    1. 事件队列:这是一个FIFO模型的队列,一方推入事件,另一方推出事件
    2. 队列的读取轮询线程组件,也就是主角Event Loop,
    3. 单独的线程池,用来执行长任务(也就是threadpool,node底层,用C++写的,不会阻塞)

    image

    在nodejs中,只有一个主线程(也就是前面说的单线程)来不断读取轮询(书中称为调用I/O观察者)队列中是否有事件。

    而对于读取文件,HTTP
    请求等(现代cpu处理能力很强,事件处理相当快,导致运行速度下降的瓶颈在I/O)比较容易堵塞的事件,就在这个单线程中执行肯定会造成堵塞,所以Event Loop
    会把这类型的事件交给底层的线程池执行,并给予线程池一个回调函数,当线程池操作
    完成这堵塞任务后,便把结果和回调函数一起再放入轮询队列中。

  • 相关阅读:
    SpringDataJpa实体类常用注解
    I2C子系统
    input子系统
    platform深入
    运用层是怎样找到驱动的+open中子设备识别
    misc设备
    文章标题
    uboot2015第一阶段---SPL
    git工具使用
    Andriod底层第五课------HAL硬件抽象层
  • 原文地址:https://www.cnblogs.com/gaoxianlyx/p/6385557.html
Copyright © 2011-2022 走看看