深入浅出node(3) 异步I/O

news/2024/7/9 18:02:59 标签: javascript, 操作系统, epoll

这篇主要整理深入浅出Node.js第三章 异步I/O

一) 异步I/O的原因 

二)异步I/O实现现状

  2.1 异步I/O与非阻塞I/O

  2.2 轮询

  2.3 理想的非阻塞异步I/O

  2.4 现实的异步I/O

三)Node的异步I/O

  3.1 事件循环

  3.2 理解异步回调函数的执行过程

    3.2.1 基础

    3.2.2 过程

四)事件驱动与高性能服务器

 

一) 异步I/O的原因  异步I/O主要有以下两点的需求

  • 用户体验  同步的模式下,在浏览器中等待服务端数据的过程中,浏览器页面会锁死   同时请求A B   同步的情况下时间为 time(A) + time(B)  异步的情况下是 时间为 Max(time(A),time(B))  并且当请求不断增长的时候,带来的差异更大
  • 异步I/O能更好的分配资源 异步I/O不会阻塞后续的运算,将原有的等待I/O的时间分配给其余的任务去执行

二) 异步I/O实现现状

  2.1 异步I/O与非阻塞I/O   对操作系统的内核来说只存在阻塞I/O和非阻塞I/O (我对书中这部分的理解是这样的 比如异步I/O是node为我们提供的一层API接口,让我们能通过非阻塞的形式去I/O)  

  操作系统对输入输出设备抽象成文件,内核在进行文件的I/O操作的时候,通过文件描述符进行管理,也就是应用程序需要I/O的时候,需要先打开文件描述符,在根据文件描述符去实现文件的读写  非阻塞I/O和阻塞I/O的区别主要在于阻塞I/O直接完成整个数据获取的流程,非阻塞I/O返回的是文件描述符,当需要获取数据的时候,在通过文件描述符去读取数据

  2.2 轮询 轮询技术主要为了解决非阻塞I/O何时完成完整的I/O而出现的  下面是轮询技术的演变过程

  • read 它通过重复检查I/O的状态来完成完整数据的读取 在得到数据前 CPU一直处于等待的状态

  • select 它在read的基础上进行了一些改进,通过对文件描述符的事件状态进行判断来完成数据的I/O  它采用一个1024长度的数据来存储状态,所以它只能同时检测1024个文件描述符

  • poll 它是在select基础上进行的改进,它采用链表的方式存储文件描述符,避免了数据的限制,但是在文件描述符很多的时候,性能有所下降

 

  • epoll  该方案是Linux下最高的事件通知机制 当没有I/O事件的时候,它会休眠(观察者),充分的利用了事件通知,执行回调来代替遍历查询 不会浪费CPU 所以执行的效率更高

  2.3 理想的非阻塞异步I/O  理想的应该是由应用程序发起异步方法,不需要遍历或者事件唤醒等方式轮询,直接进入下一个任务,在I/O完成后通过信号或者回调的方式将数据传送给应用程序

  2.4 现实的异步I/O

三) Node中的异步I/O

  3.1 事件循环  在进程启动的时候,Node会创建一个类似于while(true)的循环,每执行一次循环体称为Tick,每一次Tick的时候会查看是否有事件等待处理,如果有就取出事件并且执行相应的回调函数,没有的话就退出进程  事件循环是典型的生产者消费者模型 在Windows下这个循环基于IOCP,而在*nix基于多线程创建

 3.2 理解异步回调的执行过程

  3.2.1 基础 

  • 请求对象   从javascript发起调用到内核执行完I/O操作的过渡过程中的中间产物 所有的状态都保存在这个对象,包括送入线程池等待执行以及I/O操作完毕后的回调处理 
  •  Node中的经典调用模式 javascript调用Node的核心模块,核心模块调用C++内建模块 内建模块通过libuv(跨平台)进行系统调用

  3.2.2 过程  

  1. javascript到内建模块的调用过程中会创建一个请求对象,将javascript层传入的参数和方法都封装到这个请求对象上,回调函数会被设置到这个请求对象的oncomplete_sym上 ,供后续的调用,然后将这个请求对象推入线程池中等待执行,此时javascript的调用立即返回(底层的I/O仍然可能是阻塞或者是非阻塞的)
  2. 线程池中的I/O执行完毕后,会将结果存储在请求对象的result上,此时它会通知本身的执行状态已经完毕,并且将线程归还给线程池
  3. 在每次的Tick中,检查是否有执行完的请求,如果有将请求对象加入I/O观察者的队列,并且当做事件进行处理
  4. I/O观察者会取出事件回调函数并且将result当做参数传递给回调函数执行,这样就达到了执行回调函数的目的  

四)事件驱动与高性能服务器

  几种经典的服务器模型

  • 同步式 一次只能处理一个请求,并且其余的请求都处于等待的状态
  • 每进程/每请求 为每个请求启动一个进程,但是不具备扩展性,因为系统的资源只有那么多
  • 每线程/每请求 为每个请求启动一个线程来处理,但是线程占用一定的内存,大并发到来的时候,会造成系统运行缓慢

 Node的高性能正是因为它的事件驱动模式.

  

转载于:https://www.cnblogs.com/tiantianwaigong/p/6234961.html


http://www.niftyadmin.cn/n/997489.html

相关文章

关于axios的post用法

axios.post(, {data: params },{headers: {Access-Control-Allow-Origin:*, //解决cors头问题Access-Control-Allow-Credentials:true, //解决session问题Content-Type: application/x-www-form-urlencoded; charsetUTF-8 //将表单数据传递转化为form-data类型},withCredentia…

Python用python-docx抓取公众号文章写入word

一、安装包 pip3 install python-docx二、了解python-docx from docx import Document from docx.shared import Inchesdocument Document()#添加标题,并设置级别,范围:0 至 9,默认为1 document.add_heading(Document Title, 0…

SSH公钥认证登录

概述: SSH登录的认证方式分为两种,一种是使用用户名密码的方式,另一种就是通过公钥认证的方式进行访问, 用户名密码登录的方式没什么好说的,本文主要介绍通过公钥认证的方式进行登录。 思路: 在客户端生成公…

CorelDRAW X7绘制可爱的卡通动漫多啦A梦

今天小编为大家分享CorelDRAW X7绘制可爱的卡通动漫多啦A梦方法,教程绘制出来的哆啦A梦非常可爱,适合新手来学习,推荐过来,来看看吧! 1、新建文件 新建A4大小横向画布,双击“矩形工具”绘制与页面相同大小矩…

UNIX命令,统计当前目录(含子目录)下所有后缀为.log的文件中ERROR出现的行数...

shell程序如下所示: # cat xarg.txt #! /usr/bin/ksh for logfile in find . -name "*.log*" doecho "$logfile:"sed -n /error/ $logfile donefiles($(find . -name "*log*")) echo "The length is ${#files[]}" for fil…

ajax多次请求 从缓存取数据问题

2019独角兽企业重金招聘Python工程师标准>>> IE下,经常会出现ajax请求时从缓存中取数据,出现此情况只需要在请求后加上时间戳即可。 url : ?timestamp new Date().getTime(), 转载于:https://my.oschina.net/u/1783074/blog/715020

LInux ugo权限详解[修]

Linux 中的用户和组是用来控制使用者或者进程可以或者不可以使用哪些资源和硬件,是Linux权限控制最基本的方式。 用户和组可以看一下上一章的部分,先来看一下权限。 一、权限概览 在Linux下,使用命令ls -l显示文件详细信息 [rootHost syzhao]…

Elasticsearch核心概念

Elasticsearch核心概念 1、接近实时(NRT) Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟。 2、集群(cluster) 一个集群就是由一个或多个节点组织在一…