背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效。
已读完书籍:《架构简洁之道》。
当前阅读周书籍:《深入浅出的Node.js》。
Node 简介
了解它:Node 是什么
Node,一个强制不共享任何资源的单线程、单进程系统,包含十分适宜网络的库,为构建大型分布式应用程序提供基础设施。
Node 的目标是成为一个构建快速、可伸缩的网络应用平台。通过通信协议来组织许多 Node,非常容易通过扩展来达成构建大型网络应用的目的。
扩展:Node 给 JavaScript 带来的意义
Node 打破了过去 JavaScript 只能在浏览器中运行的局面。借助 Node,JavaScript 可以运行在不同的地方。
在 Node 中,JavaScript 可以随心所欲地访问本地文件,可以搭建 WebSocket 服务器端,可以连接数据库,可以如 Web Workers 一样玩转多进程。
熟悉它:Node 的特点
异步 I/O
在 Node 中,绝大多数的操作都以异步的方式进行调用。每个调用之间无须等待之前的 I/O 调用结束。在编程模型上可以极大提升效率。
以文件读取为例,计算两个文件读取任务的耗时。
fs.readFile('/path1', function (err, file) {
console.log(’读取文件1完成’);
});
fs.readFile('/path2', function (err, file) {
console.log(’读取文件2完成’);
});
对于同步 I/O 而言,它们的耗时是两个任务的耗时之和。而于异步 I/O 而言,它们的耗时取决于最慢的那个文件读取的耗时。
事件与回调函数
事件的编程方式具有轻量级、松耦合、只关注事务点等优势。
Node除了异步和事件外,回调函数是一大特色。回调函数是最好的接受异步调用返回数据的方式。
如下代码中,Node 创建一个Web服务器,并侦听8080端口。对于服务器,为其绑定了request事件,对于请求对象,为其绑定了data事件和end事件:
var http = require('http');
var querystring = require('querystring');
// 侦听服务器的request事件
http.createServer(function (req, res) {
var postData = '';
req.setEncoding('utf8');
// 侦听请求的data事件
req.on('data', function (chunk) {
postData += chunk;
});
// 侦听请求的end事件
req.on('end', function () {
res.end(postData);
});
}).listen(8080);
console.log(’服务器启动完成’);
单线程
Node 保持了 JavaScript 在浏览器中单线程的特点。
单线程有优点也有缺点。
1、优点
不用像多线程编程那样处处在意状态的同步问题,这里没有死锁的存在,也没有线程上下文交换所带来的性能上的开销。
2、缺点
- 无法利用多核CPU。
- 错误会引起整个应用退出,应用的健壮性值得考验。
- 大量计算占用CPU导致无法继续调用异步I/O。
跨平台
Node 支持在 Windows 和 *nix 平台上运行。得益于它在操作系统与Node上层模块系统之间构建了一层平台层架构,即libuv。
通过良好的架构,Node 的第三方 C++ 模块也可以借助 libuv 实现跨平台。目前,除了没有保持更新的 C++ 模块外,大部分 C++ 模块都能实现跨平台的兼容。
应用它:Node 的应用场景
Node 适合的场景主要有 I/O 密集型应用,而 CPU 密集型应用还有待讨论。
I/O 密集型应用
I/O 密集型指的是系统的 CPU 效能相对硬盘、内存的效能要好很多。在这种情况下,系统的大部分运作时间都是 CPU 在等待 I/O(硬盘/内存)的读写操作,因此 CPU 的使用率并不高。
Node面向网络且擅长并行 I/O,能够有效地组织起更多的硬件资源,从而提供更多好的服务。
I/O 密集的优势主要在于 Node 利用事件循环的处理能力,而不是启动每一个线程为每一个请求服务,资源占用极少。
是否不擅长 CPU 密集型业务
CPU 密集型应用给 Node 带来的挑战主要是:由于 JavaScript 单线程的原因,如果有长时间运行的计算(比如大循环),将会导致 CPU 时间片不能释放,使得后续 I/O 无法发起。
应对方案是:将大型运算任务通过适当调整和分解为多个小任务,使得运算能够适时释放,不阻塞 I/O 调用的发起,这样既可同时享受到并行异步 I/O 的好处,又能充分利用 CPU。
总结
我们来总结一下本篇的主要内容:
- Node是一个强制不共享任何资源的单线程、单进程系统,包含十分适宜网络的库,为构建大型分布式应用程序提供基础设施。
- Node 的特点主要包括异步 I/O、事件与回调函数、单线程、跨平台。
- Node 适合的场景主要有 I/O 密集型应用,而 CPU 密集型应用有挑战,但是也有应对方案。
作者介绍非职业「传道授业解惑」的开发者叶一一。《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。