Node.JS中事件轮询(Event Loop)的解析

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

网站延迟的开销

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

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

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++写的,不会阻塞)

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

而对于读取文件,HTTP

请求等(现代cpu处理能力很强,事件处理相当快,导致运行速度下降的瓶颈在I/O)比较容易堵塞的事件,就在这个单线程中

执行肯定会造成堵塞,所以Event Loop

会把这类型的事件交给底层的线程池执行,并给予线程池一个回调函数,当线程池操作

完成这堵塞任务后,便把结果和回调函数一起再放入轮询队列中。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Node.js事件循环(Event Loop)和线程池详解

    Node的"事件循环"(Event Loop)是它能够处理大并发.高吞吐量的核心.这是最神奇的地方,据此Node.js基本上可以理解成"单线程",同时还允许在后台处理任意的操作.这篇文章将阐明事件循环是如何工作的,你也可以感受到它的神奇. 事件驱动编程 理解事件循环,首先要理解事件驱动编程(Event Driven Programming).它出现在1960年.如今,事件驱动编程在UI编程中大量使用.JavaScript的一个主要用途是与DOM交互,所以使用基于事件

  • Node.JS中事件轮询(Event Loop)的解析

    当我们知道I/O操作和创建新线程的开销是巨大的! 网站延迟的开销 对于一个网站,后台大多不需要进行复杂的计算,我们的程序大多时间花费在I/O读取上. 看到一个数据:IO操作可以比数据处理慢几个数量级.高端SSD固态硬盘的读取速度可以达到200mb-700mb/s;读取1000字节需要1.4微秒.而在此期间,2GHZ频率的CPU可以执行28000个指令处理周期.而网络数据的IO甚至更慢! NodeJS采用单线程非阻塞的架构解决老大难的IO问题 当采用多线程时,为每一个请求开启一个新的线程(Apac

  • node.js中事件触发器events的使用方法实例分析

    本文实例讲述了node.js中事件触发器events的使用方法.分享给大家供大家参考,具体如下: node.js是基于事件驱动的,通过events,我们可以方便的创建事件,并通过触发事件来调用我们自定义的监听函数. 所有能触发事件的对象都应该是 EventEmitter 类的实例,一般我们自定义一个类继承于 EventEmitter 类. 通过on()方法我们可以绑定事件与监听函数: const Events = require('events'); //自定义一个类,继承于EventEmitt

  • 实例分析JS与Node.js中的事件循环

    这两天跟同事同事讨论遇到的一个问题,js中的event loop,引出了chrome与node中运行具有setTimeout和Promise的程序时候执行结果不一样的问题,从而引出了Nodejs的event loop机制,记录一下,感觉还是蛮有收获的 console.log(1) setTimeout(function() { new Promise(function(resolve, reject) { console.log(2) resolve() }) .then(() => { con

  • 详解Node.js中的事件机制

    前言 在前端编程中,事件的应用十分广泛,DOM上的各种事件.在Ajax大规模应用之后,异步请求更得到广泛的认同,而Ajax亦是基于事件机制的. 通常js给我们的第一印象就是运行在客户端浏览器上面的脚本,通过node.js我们可以在服务端运行javascript. node.js是基于单线程无阻塞异步式的I/O,异步式的I/O指的是当遇到I/O操作的时候,线程不阻塞而是进行下面的操作,那么I/O操作完成之后,线程时如何知道该操作完成的呢? 当操作完成耗时的I/O操作之后,会以事件的形式通知I/O操

  • node.js中对Event Loop事件循环的理解与应用实例分析

    本文实例讲述了node.js中对Event Loop事件循环的理解与应用.分享给大家供大家参考,具体如下: javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进入主线程,而是进入一个 "任务队列" 里,"任务队列" 通知主线程,该异步任务才会进入主线程执行. 任务的运行机制如下: 1.所有同步任务在主线程上执行,形成一个

  • node.js事件轮询机制原理知识点

    借助libuv库实现的 概括事件轮询机制:分为六个阶段 1.timers 定时器阶段 计时和执行到点的定时器回调函数 2.pending callbacks 某些系统操作(例如TCP错误类型) 3.idle,prepare 4.poll轮询阶段(轮询队列) 如果轮询队列不为空,依次同步取出轮询队列中第一个回调函数,直到轮询队列为空或者达到系统最大限制 如果轮询队列为空 如果之前设置过setImmediate函数,直接进入下一个check阶段,如果之前没有设置过setImmediate函数,在当前

  • Node.js中HTTP模块与事件模块详解

    Node.js的http服务器 通过使用HTTP模块的低级API,Node.js允许我们创建服务器和客户端.刚开始学node的时候,我们都会遇到如下代码: 复制代码 代码如下: var http = require('http'); http.createServer(function (req,res) {     res.end('Hello World\n'); }).listen(3000,"127.0.0.1"); console.log("Server funni

  • Node.js中的events事件模块知识点总结

    通过对Node的学习及应用,我们知道NodeJS其采用单线程.事件驱动.非阻塞I/O等架构设计,非常适用于高并发.I/O密集型应用. 1. 什么是事件驱动? 事件驱动,简单来说就是通过有效方法来监听事件状态的变化,并在发生变化时做出相应的动作. 举一个生活应用的场景来理解:当我们去饭店吃饭点餐,当我们下单之后,服务员告诉我们的订单号(这时候可以理解为注册了一个事件),我们在坐着等候,这时候我们的耳朵就一直监听着服务员的喊号,当喊到我们的时候,我们可以去前台取餐. 2. 事件模型 NodeJS的事

  • 深入理解Node.js中的Worker线程

    概述 多年以来,Node.js都不是实现高 CPU 密集型应用的最佳选择,这主要就是因为JavaScript的单线程.作为对此问题的解决方案,Node.jsv10.5.0 通过worker_threads模块引入了实验性的 "worker 线程" 概念,并从 Node.js v12 LTS 起成为一个稳定功能.本文将解释其如何工作,以及如何使用 Worker 线程获得最佳性能. Node.js 中 CPU 密集型应用的历史 在 worker 线程之前,Node.js 中有多种方式执行

随机推荐