Skip to content

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是对此一种延续(我的理解) img

4、Node特点

本章讲了Node的特点 异步I/O:读取文件等、事件机制驱动:模拟浏览器、回调函数 单线程:优点以及不足,child_process解决不足 扩平台:libuv解决

  • 特点1:异步I/O
    • 以读取文件为例,我们可以看到它与前端Ajax调用的方式是极其类似的
    js
      var 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