首页 > 编程语言 >阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下

阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下

时间:2024-09-08 10:54:00浏览次数:10  
标签:Node 异步 单线程 阻塞 js 线程 事件 执行

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效。

已读完书籍《架构简洁之道》。

当前阅读周书籍《深入浅出的Node.js》

异步I/O

为什么要异步I/O

1、从用户体验方面看

JavaScript在执行的时候UI渲染和响应是处于停滞状态的。如果脚本的执行时间超过100毫秒,用户就会感到页面卡顿,以为网页停止响应。

采用异步请求,在下载资源期间,JavaScript和UI的执行都不会处于等待状态,可以继续响应用户的交互行为,给用户一个鲜活的页面。

前端获取资源的速度取决于后端的响应速度。依旧可以采用异步方式享受到并发的优势,第一个资源的获取并不会阻塞第二个资源,也即第二个资源的请求并不依赖第一个资源的结束。

2、从资源分配方面看

假设业务场景中有一组互不相关的任务需要完成,现行的主流方法有以下两种:

  • 单线程串行依次执行。
  • 多线程并行完成。

多线程在多核 CPU 上能够有效提升 CPU 的利用率,但也经常面临锁、状态同步等问题。

单线程顺序执行任务的方式易于表达,但是串行执行的缺点在于性能,任意一个略慢的任务都会导致后续执行代码被阻塞。

Node 在两者之间给出了它的方案:利用单线程,远离多线程死锁、状态同步等问题;利用异步 I/O,让单线程远离阻塞,以更好地使用 CPU。

阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下_回调函数

异步I/O实现现状

操作系统对异步I/O实现的支持状况如下。

1、异步I/O与非阻塞I/O

操作系统内核对于I/O只有两种方式:阻塞与非阻塞。

在调用阻塞I/O时,应用程序需要等待I/O完成才返回结果。

非阻塞I/O跟阻塞I/O的差别为调用之后会立即返回。非阻塞I/O返回之后,CPU的时间片可以用来处理其他事务,此时的性能提升是明显的。

阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下_回调函数_02

2、理想的非阻塞异步I/O

非阻塞I/O也存在一些问题。由于完整的I/O并没有完成,立即返回的并不是业务层期望的数据,而仅仅是当前调用的状态。为了获取完整的数据,应用程序需要重复调用I/O操作来确认是否完成。

所以期望的完美的异步I/O应该是应用程序发起非阻塞调用,无须通过遍历或者事件唤醒等方式轮询,可以直接处理下一个任务,只需在I/O完成后通过信号或回调将数据传递给应用程序即可。

阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下_非阻塞_03


3、现实的异步I/O

现实要达成理想异步I/O的目标,并非不可能。

通过让部分线程进行阻塞I/O或者非阻塞I/O加轮询的技术来完成数据获取,让一个线程进行计算处理,通过线程之间的通信将I/O得到的数据进行传递,这就轻松实现了异步I/O(尽管它是模拟的)。

阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下_非阻塞_04

Node的异步I/O

事件循环、观察者、请求对象、I/O线程池这四者共同构成了Node异步I/O模型的基本要素。

1、事件循环

在进程启动时,Node便会创建一个类似于while(true)的循环,每执行一次循环体的过程被称为Tick。

每个Tick的过程就是查看是否有事件待处理,如果有,就取出事件及其相关的回调函数。如果存在关联的回调函数,就执行它们。然后进入下个循环,如果不再有事件处理,就退出进程。

2、观察者

每个事件循环中有一个或者多个观察者,而判断是否有事件要处理的过程就是向这些观察者询问是否有要处理的事件。

事件循环是一个典型的生产者/消费者模型。异步I/O、网络请求等则是事件的生产者,源源不断为Node提供不同类型的事件,这些事件被传递到对应的观察者那里,事件循环则从观察者那里取出事件并处理。

3、请求对象

对于Node中的异步I/O调用而言,回调函数却不由开发者来调用。从JavaScript发起调用到内核执行完I/O操作的过渡过程中,存在一种中间产物,它叫做请求对象。

如下代码,fs.open()的作用是根据指定路径和参数去打开一个文件,从而得到一个文件描述符,这是后续所有I/O操作的初始操作。

fs.open = function(path, flags, mode, callback) {
  // ...
  binding.open(pathModule._makeLong(path),
                stringToFlags(flags),
                mode,
                callback);
};

4、执行回调

组装好请求对象、送入I/O线程池等待执行,实际上完成了异步I/O的第一部分,回调通知是第二部分。

I/O观察者回调函数的行为就是取出请求对象的result属性作为参数,取出oncomplete_sym属性作为方法,然后调用执行,以此达到调用JavaScript中传入的回调函数的目的。

阅读周·深入浅出的Node.js | 异步I/O、事件驱动和单线程,Node基调三元素了解一下_非阻塞_05

非I/O的异步API

Node中还存在一些与I/O无关的异步API,它们分别是setTimeout()、setInterval()、setImmediate()和process.nextTick()。

1、定时器

setTimeout()和setInterval()与浏览器中的API是一致的,分别用于单次和多次定时执行任务。

2、process.nextTick()

process.nextTick()方法的操作相对较为轻量,也更高效。process.nextTick()的回调函数保存在一个数组中,在每轮循环中会将数组中的回调函数全部执行完。

3、setImmediate()

setImmediate()方法与process.nextTick()方法十分类似,都是将回调函数延迟执行。setImmediate()的结果则是保存在链表中,在每轮循环中执行链表中的一个回调函数。

事件驱动与高性能服务器

事件驱动的实质,即通过主循环加事件触发的方式来运行程序。

Node通过事件驱动的方式处理请求,无须为每一个请求创建额外的对应线程,可以省掉创建线程和销毁线程的开销,同时操作系统在调度任务时因为线程较少,上下文切换的代价很低。这使得服务器能够有条不紊地处理请求,即使在大量连接的情况下,也不受线程上下文切换开销的影响,这是Node高性能的一个原因。

Node是一套高性能的平台,可以利用它构建与Nginx相同的功能,也可以处理各种具体业务,而且与背后的网络保持异步畅通。

总结

我们来总结一下本篇的主要内容:

  • 异步I/O、事件驱动和单线程,它们构成Node的基调。
  • 事件循环是异步实现的核心,它与浏览器中的执行模型基本保持了一致。
  • Node依靠构建了一套完善的高性能异步I/O框架,打破了JavaScript在服务器端止步不前的局面。

作者介绍非职业「传道授业解惑」的开发者叶一一。《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。如果看完文章有所收获,欢迎点赞

标签:Node,异步,单线程,阻塞,js,线程,事件,执行
From: https://blog.51cto.com/u_15838863/11951293

相关文章

  • Vue 多个服务的路由配置 在 vue.config.js 里面怎么写
    在Vue项目的vue.config.js文件中,你不能直接配置路由服务,因为这个文件主要用于配置Webpack和开发服务器等项目设置。路由配置通常是在Vue项目的代码中设置的,例如在router/index.js文件中。不过,如果你需要配置多个服务(即不同的API服务或代理服务),你可以在vue.config.js......
  • 基于nodejs+vue动漫论坛[程序+论文+开题] 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,动漫文化作为一种全球化的流行文化现象,在全球范围内吸引了大量忠实粉丝。动漫论坛作为动漫爱好者交流思想、分享作品、探讨剧情的......
  • 基于nodejs+vue动漫模型仓储管理系统[程序+论文+开题] 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着动漫产业的蓬勃发展,动漫模型作为该领域的重要衍生品,其市场需求日益增长。动漫模型种类繁多,从精致的手办到复杂的场景模型,每一款都承载着粉丝的热情与期......
  • Vue2 - 详细实现聊天室IM即时通讯及聊天界面,支持发送图片视频、消息已读未读等,集成mqt
    前言如果您需要Vue3版本,请访问在vue2|nuxt2项目开发中,详解手机移动端H5网页在线1v1聊天功能(仿腾讯云IM功能),技术栈为MQTT通讯协议+后端Node服务端+数据库设计+vue前端聊天界面,超详细前后端完整流程及示例源代码,vue2聊天即时通讯IM实时接收和发送消息,可发送文字、图......
  • nodejs 返回静态资源
    nodejs返回资源时,依照index.js文件的目录为基准。例如,index.js存放目录为/web/index.js 模板文件中的静态资源存放在./static/main.css那么静态资源的实际存放目录就是/web/static/main.css.这个文件夹要和index.js在同一个目录下才可以。 nodejs返回css无效当nodejs......
  • 优爱酷酷采系统软件支持批量链接采集可指定深度、资源嗅探支持10大类资源,批量下载短视
    图文详情如何批量嗅探资源采集网页链接?图像音频视频JsCssHtmlJson文档字体压缩其它自动下载链接转换仿站批量格式转换.webP,.avif格式图片下载,优爱酷酷采系统-想采就采把握精彩留住美好下载:UiCool.cn 【优爱酷酷采系统】✅链接:https://www.alipan.com/s/LxDVE3pjN......
  • [Redis]Redis到底是单线程还是多线程程序?
    概述这里我们先给出问题的全面回答:Redis到底是多线程还是单线程程序要看是针对哪个功能而言,对于核心业务功能部分(命令操作处理数据),Redis是单线程的,主要是指Redis的网络IO和键值对读写是由一个线程来完成的,这也是Redis对外提供键值存储服务的主要流程,所以一般我们认为Red......
  • 基于Node.js+vue招聘系统的设计与实现(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景在当今竞争激烈的就业市场中,招聘活动的高效性与精准性对于企业吸引并留住人才至关重要。传统的招聘方式往往依赖于招聘会、报纸广告或第三方招聘平台,这些方......
  • 基于Node.js+vue基于的养老服务(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着全球人口老龄化的加速,养老服务已成为社会关注的焦点。传统养老模式面临诸多挑战,如资源分配不均、服务质量参差不齐、老年人精神生活匮乏等。在此背景下,......
  • 基于Node.js+vue基于SpringBoot的电脑商城(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,电子商务已成为现代商业活动的重要组成部分。电脑商城作为电子产品销售的重要渠道,其线上化趋势日益明显。传统的电脑商城面临着运......