Node.js 中的阻塞和非阻塞io

简介: Node.js 中的阻塞和非阻塞io

前言

      Node.js 是运行在服务端的 JavaScript,它具备可以处理高并发的能力,这一章作为nodejs系列文章的第一章,我们将介绍nodejs之所以性能好的原因

正文

共享状态的并发

      node为javascript引入了一个复杂的概念,共享状态的并发,通俗讲,node中你需要对回调函数如何修改当前内存中的变量特别小心,除此之外,你还要特别注意对错误的处理是否会潜在改变这些状态导致整个进程不可使用,什么意思呢,我们举个例子进一步说明:

640.png

      这里我们假设一个用户像node服务器同时发出/books的请求,结果会是怎么样的呢,node会将完整的图书列表返回给第一个请求,但是把一个空的图书列表返回给第二个请求。为什么会有这样一个与传统服务器端语言不同的结果呢

      两者区别主要就在于基础架构上,node采用的是一个长期运行的进程,相反,Apache会产出多个线程(每个请求一个线程),每次都会刷新状态。而在传统语言中,变量books会被重新赋值,而node中不然,serveBooks函数会被再次调用,且作用域中的变量不受影响,不会重新赋值(也就是仍然保持被修改为空数组后的状态)


阻塞

      node.js和javascript一样,使用了事件轮询,因为毕竟是基于javascript的API,这也意味着node.js虽然是单线程执行的,但是却不会被阻塞。我们来看下面的例子:

640.png

      下面这段代码在我电脑上的运行结果是这样的:

640.png

      为什么和预期的结果不一样呢,因为事件轮询被javascript代码阻塞了,由于第一个定时函数的回调函数执行了很长时间(循环次数很多),所以下一个事件轮询执行的时间就远远超过了2s。所以这样的行为方式并不是很理想的,事件轮询是Node IO的基础核心,意味着如果出现阻塞,HTTP服务器每秒处理的请求数量就会减少,效率也会降低


非阻塞

      正因为如此,许多优秀的Node模块都是非阻塞的,执行任务也都采用了异步的方式。既然执行时只有一个线程,也就是说,当一个函数执行时,同一时间不可能有第二个函数也在执行,那么node.js又是如何做到高并发的呢

      其实Node的最大并发量就是1,因为是单线程,并不提供真正的并行操作,关键在于,在调用堆栈执行非常快的情况下,同一时刻你无须处理多个请求,v8搭配非阻塞io,就可以帮助从执行速度和非阻塞上实现伪并行


错误处理

      node应用依托在一个拥有大量共享状态的大进程中,在一个HTTP请求,如果某个回调函数发生错误,整个进程都会出错:

      因为错误未被捕获,所以访问的时候会导致进程崩溃640.png

node这么处理的原因就是因为,在发生未被捕获的错误时,进程的状态就不确定了,之后就可能无法正常工作了,并且如果错误始终不被处理的话,就会一直抛出意料之外的错误,这样很难调试。所以,错误处理中,每一步都很重要,因为它能让你书写更安全的程序,并且不丢失出发错误的上下文信息


小结

      我们知道Node通过单线程的执行环境,提供了极大的简便,不过,也正因如此,当你书写网络应用时,要尽可能避免使用同步IO,并且该线程中的所有状态都是维护在一个内存空间中的,换句话说,写程序的时候修改变量的时候就要格外小心

目录
相关文章
|
27天前
|
存储 缓存 算法
如何优化阻塞IO的性能?
【10月更文挑战第6天】如何优化阻塞IO的性能?
31 5
|
2月前
|
JSON 前端开发 JavaScript
socket.io即时通信前端配合Node案例
本文介绍了如何使用socket.io库在Node.js环境下实现一个简单的即时通信前端配合案例,包括了服务端和客户端的代码实现,以及如何通过socket.io进行事件的发送和监听来实现实时通信。
35 2
|
3月前
|
存储 Java 数据库连接
BIO阻塞IO流与数据存储大揭秘:性能与资源消耗,一文让你彻底解锁!
【8月更文挑战第25天】本文探讨了Java中BIO阻塞IO流与数据存储的概念及其实现。BIO作为一种传统IO模型,在处理每个客户端请求时需创建新线程并等待响应,这在并发量大时会导致性能下降和高资源消耗。示例代码展示了如何利用`ServerSocket`实现基于BIO的简单服务器。此外,文章还介绍了数据存储的基本方法,例如通过`BufferedWriter`向文件写入数据。两者对比显示,BIO适合连接数稳定的场景,而数据存储则适用于需要持久化保存信息的情况。通过这些分析和实例,希望能帮助读者更好地掌握这两种技术的应用场景及其优缺点。
43 0
|
3月前
|
C# 开发者 设计模式
WPF开发者必读:命令模式应用秘籍,轻松简化UI与业务逻辑交互,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,命令模式是简化UI与业务逻辑交互的关键技术,通过将请求封装为对象,实现UI操作与业务逻辑分离,便于代码维护与扩展。本文介绍命令模式的概念及实现方法,包括使用`ICommand`接口、`RelayCommand`类及自定义命令等方式,并提供示例代码展示如何在项目中应用命令模式。
46 0
|
3月前
|
Ubuntu Linux
内核实验(九):添加IO驱动的阻塞读写功能
本文通过修改内核模块代码,介绍了如何在Linux内核中为IO驱动添加阻塞读写功能,使用等待队列和条件唤醒机制来实现读写操作的阻塞和非阻塞模式,并在Qemu虚拟机上进行了编译、部署和测试。
16 0
|
3月前
|
JavaScript 前端开发 Ubuntu
如何在 VPS 上安装 Express(Node.js 框架)并设置 Socket.io
如何在 VPS 上安装 Express(Node.js 框架)并设置 Socket.io
53 0
|
4月前
|
Java
什么是阻塞IO?
**阻塞IO是一种IO操作模式,使得调用线程在IO未完成时会暂停,等待操作完成。简单但可能导致线程阻塞,适用于低并发、长处理场景。Java示例中,`ServerSocket`和`Socket`展示了这种模式。服务端接收到客户端连接后读取数据,回应"Echo",每个连接需单独线程处理。高并发时可考虑非阻塞IO(NIO)或异步IO来优化。**
|
3月前
|
存储 JavaScript 数据库
如何使用 Socket.IO、Angular 和 Node.js 创建实时应用程序
如何使用 Socket.IO、Angular 和 Node.js 创建实时应用程序
25 0
|
4月前
|
缓存 网络协议 算法
【Linux系统编程】深入剖析:四大IO模型机制与应用(阻塞、非阻塞、多路复用、信号驱动IO 全解读)
在Linux环境下,主要存在四种IO模型,它们分别是阻塞IO(Blocking IO)、非阻塞IO(Non-blocking IO)、IO多路复用(I/O Multiplexing)和异步IO(Asynchronous IO)。下面我将逐一介绍这些模型的定义:
185 1
|
JavaScript 前端开发 数据库
Node.js 阻塞与非阻塞概述
Node.js 阻塞与非阻塞概述