极简 Node.js 入门 - Node.js 是什么、性能有优势?
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node
本文更佳阅读体验:https://www.yuque.com/sunluyong/node/what-is-node
定义
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine.
现在 Node.js 官网的定义就这么简单,但也可以看出几个最重要的特征
- Node.js 不是一门语言,是一个运行时,和浏览器更像,只不过运行在服务端
- 这个运行时的方言是 JavaScript(不包含 BOM、DOM API,增加了 Stream、网络等 API)
- Node.js 是靠 Chrome V8 引擎运行 JavaScript
对应到 Java 我们可以理解 Node.js 是 JDK,装上就能在服务端跑 JavaScript 代码了。
Chrome 和 Node.js 同样是 JavaScript 运行时,都使用了 V8 引擎,主要区别在于 V8 只实现了 ECMAScript 的数据类型、对象和方法,Chrome 运行时提供了 Window、DOM、BOM,而 Node.js 运行时提供了global、 Buffer、net 等模块
下面内容需要一些计算机基础知识,但看不懂并不影响 Node.js 的学习
事件驱动 & 非阻塞 I/O 是什么
在 Node.js 才诞生的时候大家总是充满了好奇,早期官网上的介绍要更多一些,主要说了 Node 最核心的两个特性:事件驱动、非阻塞 I/O
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
举个例子理解 Node.js 和之前大部分 web 应用编程区别,当读取数据库的时候会写出这样的代码
var result = db.query('select * from...');
I/O 是一个相对耗时较长的工作(这是后面讨论的前提),I/O 任务主要由 CPU 分发给 DMA 执行,等待数据库查询结果的时候进程在做什么?大部分时候就是单纯在等着而已
不同硬件设备 I/O 操作所花费 CPU cycles
Action Cost (CPU cycles)
L1 Cache* 3
L2 Cache* 14
RAM* 250
Disk 41,000,000
Network 240,000,000
这明显是在浪费 CPU,所以有了多线程的性能优化手段,但学习操作系统的时候我们就知道
- 操作系统创建线程和切换多和线程上下文需要一定的开销
- 因为多线程带来的执行堆栈是要占用内存的
- 多线程变成面对的死锁、状态同步等问题会增加使用的复杂性
上面的代码要么阻塞整个进程,要么使用了多线程,如果进程不等待 I/O 结果,直接处理后续任务就是非阻塞 I/O,这样可以不用浪费 CPU
db.query('select * from...', function (result) {
// 消费 result
});
在 Promise、async|await 没有的年代,回调是异步的通用处理方式
进程如何获知异步 I/O 调用完成,触发回调函数呢?这就要靠 Event Loop 实现,也就是上面提到的事件驱动
这个图看起来非常复杂,有几个要点可以帮助理解
- 在 Node.js 中所有操作称之为事件,客户端的请求也是事件,所有事件维护在图中最左侧的事件队列中
- Node.js 主线程也就是图中间的循环就是 Event Loop,主要作用是轮训事件队列中是否存在事件
- 有非阻塞事件,按照先进先出原则依次调用处理
- 有阻塞事件,交给图中最右侧的 C++ 线程池处理,线程池处理完成后把结果通过 Event Loop 返回给事件队列
- 进行下一次循环
- 一个请求所有事件都被处理,把响应结果发给客户端,完成一次请求
这样一个请求 - 响应模型就完成了,如果在 Event Loop 中包含同步的 CPU 密集操作,就会阻塞主线程
Node.js 性能真的高吗?
要回答这个问题首先需要了解几个基本常识
- CPU 运算远远快于 I/O 操作
- Web 是典型的 I/O 密集场景
- JavaScript 是单线程,但 JavaScript 的 runtime Node.js 并不是,负责 Event Loop 的 libuv 用 C 和 C++ 编写
很多语言是依赖的多线程解决高并发,一个线程处理一条用户请求,处理完成了释放线程,在阻塞 I/O 模型下, I/O 期间该用户线程所占用的 CPU 资源(虽然十分微量,大部分交给了 DMA)什么都不做,等待 I/O,然后响应用户,而且开启多个进程/线程 CPU 切换 Context 的时间也十分可观
就像饭店的服务员只负责点菜,如果给每个厨师都配一个服务员,服务员把客人菜单给大厨后就玩手机等着一样,你是老板你也生气,况且不同于饭店大厨工资高于服务员,在计算机世界,CPU 资源比 I/O 宝贵的多
说 Node.js 在高并发、I/O 密集场景性能高,也就是 Web 场景性能高主要也是解决这个问题,没必要一个厨师配一个服务员,整个饭店说不定一个服务员就够了,剩下的钱可以随便做其它事情
用户请求来了, CPU 的部分做完不用等待 I/O,交给底层完成,然后可以接着处理下一个请求了,快就快在
- 非阻塞 I/O
- Web 场景 I/O 密集
- 没多线程 Context 切换开销,多出来的开销是维护 EventLoop
其它场景 NodeJS 性能确实不高,甚至非常低下,感兴趣可以看一下 Apache(多进程) 和 Nginx(事件驱动) 对比,现在大型 web 应用普遍是 Nginx 在最前面做负载均衡服务器、静态资源服务器,Apache 在下一层做实际 Web Server,响应动态请求
因此 Node.js 在 I/O 密集的 Web 场景相对于使用多进程模型语言有性能优势,这个优势不是来源于语言,而是操作系统实现,Java 按照这种模型实现性能一样很高
得益于 V8 的优化和 C/C++ 拓展,Node.js 执行 CPU 密集任务性能并不差,但如果长时间进行 CPU 运算会阻塞后续 I/O 任务发起,用 Java 实现非阻塞模型也会遇到一样问题
参考
- Node.js 作者 Ryan Dahl 介绍 Node.jsRyan Dahl 2009 JSconf - Node.js.pdf
- NGINX 如何实现高性能和可扩展性
- 深入理解 JavaScript Event Loop
极简 Node.js 入门 - Node.js 是什么、性能有优势?的更多相关文章
- Node.js入门-Node.js 介绍
Node.js 是什么 Node.js 不是一种独立的语言,与 PHP,Python 等"既是语言优势平台"不同,它也不是一个 JavaScrip 框架,不同于 CakePHP,D ...
- Vue.js 入门 --- vue.js 安装
本博文转载 https://blog.csdn.net/m0_37479246/article/details/78836686 Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据 ...
- js入门 关于js属性及其数据类型(详解)
1. js的本质就是处理数据.数据来自于后台的数据库. 所以变量就起到一个临时存储数据的作用. ECMAScript制定了js的数据类型. 数据类型有哪些? 1. 字符串 String 2. 数字 ...
- js入门关于js‘i++’‘++i’和‘i--’‘--i’计算的问题
一,i++和++i; i++是先赋值在运算,++i是先运算在赋值: 例如:var a=1 a++:在运算时是按照1计算的:但在下面再次出现时是按照2进行运算: ++a:在运算时是按照2计算的:在下面再 ...
- 极简 Node.js 入门 - 1.2 模块系统
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 1.3 调试
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 1.4 NPM & package.json
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 2.1 Path
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 2.2 事件
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
随机推荐
- (数据科学学习手札89)geopandas&geoplot近期重要更新
本文示例代码及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 最近一段时间(本文写作于2020-07-1 ...
- bugku extract 变量覆盖
- Django13 /缓存、信号、django的读写分离
Django13 /缓存.信号.django的读写分离 目录 Django13 /缓存.信号.django的读写分离 1. 缓存 2. 信号 3. django的读写分离 1. 缓存 缓存简述: 缓存 ...
- Python并发编程01 /操作系统发展史、多进程理论
Python并发编程01 /操作系统发展史.多进程理论 目录 Python并发编程01 /操作系统发展史.多进程理论 1. 操作系统 2. 进程理论 1. 操作系统 定义:管理控制协调计算机中硬件与软 ...
- DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)
前言 曲面细分是Direct3D 11带来的其中一项重要的新功能.它引入了两个可编程着色器阶段以及一个固定的镶嵌处理过程.简单来说,曲面细分技术可以将几何体细分为更小的三角形,并以某种方式把这些新生成 ...
- uPDF-功能强大的PDF文件处理小工具
前几天因为工作原因,需要将一个PDF压缩一下. 网上找了半天,要么收费,要么就是转换的质量不太好.论坛也找到一些破解的软件,但是总有点不太合适,有些功能还挺复杂.也有些在线转换的,又考虑到自己较为隐私 ...
- 互联网的寒冬下各大一线互联网公司还在用SpringBoot这是为什么?
引言 现在各大技术社区 Spring Boot 的文章越来越多,Spring Boot 相关的图文.视频教程越来越多,使用 Spring Boot 的互联网公司也越来越多: Java 程序员现在出去面 ...
- ffmpeg播放器实现详解 - 框架搭建
ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and port ...
- DQL:查询表中的记录
DQL:查询表中的记录 * select * from 表名; 1. 语法: select 字段列表 from 表名列表 where 条件列表 group by 分组字段 having 分组之后的条件 ...
- /dev/mapper/VolGroup00-LogVol00 满了,根目录存储垃圾文件导致磁盘满了
登录系统,df -H 发现磁盘存储快满了 解决办法 1. 使用命令查出根目录下大的垃圾文件 使用 du -sh /* | sort -nr 查看根目录下的的大文件,找的不要的 rm -rf 使用 fi ...