Node.js 的对比优劣势和学习路线
1. 前言
本节课将会引导大家学习了解:
- Node.js 的优劣势,它适合做什么
- 本课程的学习路线
2. Node.js 的对比优势
2.1 高并发
Node.js 在高并发上有优势,其原因是 Node.js 运用的非阻塞异步模式。在这里解释一下原理:
首先我们需要一些前置条件
- Node.js 是单线程执行,它同一时刻只能执行一句代码;
- Node.js 的线程 CPU 计算和其他 I/O 操作(文件 I/O、网络 I/O 等)可以同时运行;
不难猜想出一个性能优化的方法,如果我们在执行 I/O 操作时,执行其他需要运用 CPU 线程计算的代码,就可以压缩程序达到某种功能的消耗时间。
我们来看一个便于理解的例子,假设有建筑工、搬运工:
故事一
请了建筑工和搬运工各一个:
第一天:建筑工休息、搬运工搬砖块,搬够一天的量,通知建筑工砌墙。
第二天:搬运工休息、建筑工砌墙,把砖块用完,通知搬运工来搬砖块。
第三天:建筑工休息、搬运工搬砖块,搬够一天的量,通知建筑工砌墙。
第四天:搬运工休息、建筑工砌墙,砌墙完成,通知搬运工来搬砖块。
如此往复,40天后完工...
结果工时大大延长,超过了时限。
故事二
请了建筑工和搬运工各五个:
第一天:建筑工休息、搬运工搬砖块,搬够五个人一天的量,通知建筑工砌墙。
第二天:搬运工休息、建筑工砌墙,把砖块用完,通知搬运工来搬砖块。
第三天:建筑工休息、搬运工搬砖块,搬够一天的量,通知建筑工砌墙。
第四天:搬运工休息、建筑工砌墙,把砖块用完,通知搬运工来搬砖块。
如此往复,8天后完工...
结果工资耗费巨大,超过了工程预算,还没有完成工程,团队奔溃。
故事三
请了建筑工和搬运工各两个:
第一天:建筑工休息、搬运工搬砖块,搬够两个人一天的量,通知建筑工砌墙。
第二天:搬运工继续搬砖块、建筑工砌墙,备用砖块余量不变。
第三天:搬运工继续搬砖块、建筑工砌墙,备用砖块余量不变。
第四天:搬运工继续搬砖块、建筑工砌墙,备用砖块余量不变。
如此往复,11天后完工...
结果工时工资合理,本次工程完美完成。
在这个例子中:
- 建筑工是 CPU,做的是计算类工作
- 搬运工是在 Node.js 中可异步的 I/O 操作,为了获取数据给 CPU 做运算
在上面三个故事中,体现了各种不同的思维:
- 故事一:单线程阻塞
- 故事二:多线程阻塞
- 故事三:非阻塞异步
由此可见,Node.js 非阻塞异步模式的设计,是能在多并发的时候减少性能浪费,充分利用各个闲置资源来给程序提速。
2.2 开发优势
- 对于前端开发者而言,减轻了重新学语言的负担。
- 不用多做线程控制,Node.js 事件循环机制和事件驱动核心,能够让开发者使用简单的回调函数、Promise 就能控制好程序控制权的关键流动,剩余的交给 Node.js 就好了。
- 生态活跃、强大带来了大量先进技术的兼容,几乎所有的先进的现代技术在 npm 上都有库。甚至新的一些数据库( MongoDB 等)的查询是用 JavaScript 开发的,这侧面体现了 Node.js 生态的强大。
3. Node.js 的劣势
3.1 计算密集型程序
计算密集型程序指需要大量 CPU 运算的的程序
Node.js 在 CPU 计算密集的程序中,表现比较不如意,这也非常好理解,上文提到 Node.js 的优势在于它能活用 CPU 和其他 I/O 操作同时执行,充分利用。
我们通过下面一张表来了解下和其他后端语言对比中,Node.js 大概的性能表现。需要注意的是,这里做的是简单不停地累加1,在100万、1000万、1亿次的表现(取10次平均值):
语言 | 100万(ms) | 1000万(ms) | 1亿 (ms) |
---|---|---|---|
node | 20.526 | 182.563 | 1718.001 |
go | 0.995 | 96.995 | 79.206 |
python | 167.646 | 1722.714 | 17750.904 |
java | 2.700 | 6.200 | 36.200 |
php | 181.705 | 1813.984 | 18088.967 |
注:go在1000万时表现比在1亿时表现差,是因为不稳定导致,在1000万时出现一次646.25ms的表现,拉高了平均水平导致。
由此可见,go 和 Java 在计算密集型程序中,表现均比 Node.js 优秀,而 Node.js 比 python 和 php 表现更优秀。
3.2 动态问题
JavaScript 是一种动态语言,如果是一个人或者一个合作无间的小团队做的中小型项目,这甚至不是一个劣势,而是让程序多变、容错性高的优势。
但是在复杂系统,或者多人维护的系统中,很可能会发现 JavaScript 的函数、变量在传递的过程中类型被不停改变。导致维护成本升高。
而这个问题可以用 TypeScript(JavaScript 的强类型超集)解决,或者通过严格的开发规范控制损伤。
4. 本课程学习路线
本系列结合 express 系列 遵从螺旋升高学习法。
- 会先介绍在不使用框架的情况下,怎么样使用纯粹的 Node.js 实现对机器的监控、对本地文件操作、怎么编写接口。
- 而后再介绍怎么使用框架、库来优化纯粹 Node.js 实现的功能,优化编写体验和项目结构。
下面为先贴出本系列文档的框架设计
本系列文档设计路线,也是笔者推荐的学习路线。我们会先学习一些基础库,利用它们来读取一些机器信息、读写一些本地文件、和利用纯粹的 Node.js 编写一些接口。
在完成这部分的学习之后,读者应该有基础的接口编写能力,实现从 0 到 1。
而后会介绍多进程、一些常用第三方库的使用,并且介绍与数据库的连接、操作等技术。
学习完这些后,读者应该有在不适用框架的情况下,具有代码编写、数据库操作、本地文件操作、转发(代理)等能力。
完成 Node.js 学习后,推荐阅读 express 框架的文档,来优化代码结构,提升编写体验和降低维护难度。同时通过学习 express 框架,对 Node.js 的众多框架产生初步理解。
但请记住 ==在学习的过程中,实践是深化理解的利器。==
5. 小结
本节课程我们主要学习了 Node.js 的优劣势 、本课程的学习路线。
重点如下:
-
重点1
Node.js 的优势在于便于开发、善于应对高并发。
-
重点2
Node.js 的劣势在于不适合应用于处理 计算密集型 任务、过于灵活,多人开发或复杂系统开发需要外部力量限制灵活度。
-
重点3
本课程的学习路线遵从螺旋升高学习法,适合新手顺序阅读。如果希望获取特定词条的解释,需要翻阅目录。