1简介
1、诞生
- 2009年,Ryan Dahl 发布
2、由来及发展
这一章主要讲了 node使用js作为实现语言的由来:js符合作者预期 和node名字的由来:网络功能节点
- 1、作者的初衷就是
- 设计一款基于事件驱动、非阻塞I/O的Web服务器,达到高性能
- 评估了C、Lua、Haskell、Ruby,都不理想
- js评估
- js 后端历史包袱为零 采用非阻塞I/O
- 浏览器广泛的事件驱动
- v8高性能引擎
- node而生,js成为其实现语言
- 2、为什么叫node
- 最后发展超过了他最初单纯开发一个Web服务器的想法
- 变成了构建网络应用的一个基础框架
- 包含:服务器、客户端、命令行工具
- 最终:
- 为一个强制不共享任何资源的单线程、单进程系统,
- 包含十分适宜网络的库,
- 为构建大型分布式应用程序提供基础设施
- 成为一个构建快速、可伸缩的网络应用平台
- 通过通信协议来组织许多Node,
- 非常容易通过扩展来达成构建大型网络应用的目的
- 每一个Node进程都构成这个网络应用中的一个节点
- 因此叫node就符合了这个款产品的定位
3、node 意义
这一章讲了node诞生产生意义 主要是js以后可以再服务器端大展拳脚 js在浏览器端和服务器端做了对比
- 浏览器中局限
- h5和js的能力
- 来于webkit 和 v8
- 取决于浏览器中间层提供的支持有多少
- 长久以来却限制在浏览器的沙箱中运行
- Nodejs 与 浏览器 对比
- 都是基于事件驱动的异步架构
- 浏览器
- 通过事件驱动来服务界面上的交互
- Node
- 通过事件驱动来服务I/O
- 并且功能得到拓展:随心所欲地访问本地文件,可以搭建WebSocket服务器端,可以连接数据库
- Node不处理UI,但用与浏览器相同的机制和原理运行
- 也有对两者同时运用的尝试
- 出现node-webkit这样的项目(2012年)
- Node中的事件循环和WebKit的事件循环融合在一起,
- 既可以通过它享受HTML、CSS带来的UI构建,
- 也能通过它访问本地资源,将两者的优势整合到一起
- github未找到项目(2024年),可能已经过时
- 像后来的nuxt是对此一种延续(我的理解)
- 出现node-webkit这样的项目(2012年)
4、Node特点
本章讲了Node的特点 异步I/O:读取文件等、事件机制驱动:模拟浏览器、回调函数 单线程:优点以及不足,child_process解决不足 扩平台:libuv解决
- 特点1:异步I/O
- 以读取文件为例,我们可以看到它与前端Ajax调用的方式是极其类似的
jsvar fs = require('fs'); fs.readFile('/path', function (err, file) { console.log(’读取文件完成’) }); console.log(’发起读取文件’);
- 在Node中,绝大多数的操作都以异步的方式进行调用。
- Ryan Dahl排除万难,在底层构建了很多异步I/O的API:例如文件读取、网络请求等
- 从语言层面很自然地进行并行I/O操作
- 特点2:事件
- 将前端浏览器中应用广泛且成熟的事件引入后端,配合异步I/O,将事件点暴露给业务逻辑。
- 为其绑定了request事件,对于请求对象,我们为其绑定了data事件和end事件js
var http = require('http'); // 侦听服务器的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(’服务器启动完成’);
- 事件编程特点:轻量级、松耦合、只关注事务点等优势
- 问题:事件与事件之间各自独立,如何协作是一个问题。
- 特点3:回调函数
- 回调函数无处不在
- 回调函数也是最好的接受异步调用返回数据的方式。
- 特点4:单线程
- Node保持了JavaScript在浏览器中单线程的特点
- 优点:
- 避免了多线程问题
- 多线程编程那样处处在意状态的同步问题
- 这里没有死锁的存在,
- 也没有线程上下文交换所带来的性能上的开销
- 不足:
- 无法利用多核CPU
- 错误会引起整个应用退出,应用的健壮性值得考验
- 大量计算占用CPU导致无法继续调用异步I/O
- 解决不足:
- Node采用了与Web Workers相同的思路
- 来解决单线程中大计算量的问题:child_process
- 从容地应对单线程在健壮性和无法利用多核CPU方面的问题。
- 将计算分发到各个子进程,
- 可以将大量计算分解掉,
- 然后再通过进程之间的事件消息来传递结果,
- 这可以很好地保持应用模型的简单和低依赖
- 特点5:跨平台
- Node基于libuv实现跨平台的架构示意图
- 兼容Windows和*nix平台主要得益于Node在架构层面的改动
- 它在操作系统与Node上层模块系统之间构建了一层平台层架构,即libuv。
- 目前,libuv已经成为许多系统实现跨平台的基础组件
- Node的第三方C++模块也可以借助libuv实现跨平台。
5、应用场景
本章主要讲了Node的使用场景,包括 I/O密集型 如胜任CPU密集型业务:c++扩展、子进程 遗留系统:使用老接口 分布式数据库查询
- 1、I/O密集型
- Node面向网络且擅长并行I/O,能够有效地组织起更多的硬件资源
- 主要在于Node利用事件循环的处理能力
- 2、CPU密集型业务
- 收否胜任?
- V8的执行效率非常高,和其他语言相比速度也非常快
- 主要挑战是:js单线程,如果长时间运行计算,使得后续I/O无法发起
- 解决方法:
- 调整、分解大型运算任务为多个小任务,
- 运算适时释放,
- 不阻塞I/O调用发起
- 对于一个纯计算的场景,或许根本没有I/O,改用多线程
- Node没有多线程,如何解决?
- Node可以通过编写C/C++扩展的方式更高效地利用CPU
- 子进程处理
- CPU密集不可怕,如何合理调度是诀窍
- 3、遗留系统处理
- 对待原来的旧系统,譬如java/jsp
- 旧有的系统具有非常稳定的数据输出,持续为传统网站服务,
- 同时为移动版提供数据源,Node将该数据源当做数据接口,发挥异步并行的优势
- 旧系统只做接口和中间件
- 4、分布式应用
- 并行地去多台数据库中获取数据并合并
- NodeFox能实现对多台MySQL数据库的查询,如同查询一台MySQL一样,
- 而ITier更强大,查询多个数据库(不同的数据库)如同查询单个数据库一样
- Node高效利用并行I/O的过程,也是高效使用数据库的过程
总结
- 第一篇讲的是一些概念,但是非常重要,例如异步、事件(事件驱动)、回调、非阻塞、I/O、libuv等
- 之前java同事问我,node到底是个啥?我其实都没有答好,在他们看来是服务器应该像阿帕奇之类的,怎么还用js做开发呢,现在理解node其实是一个综合体,既包括服务器,也包括运行时的环境,使用v8