Node.js的技术架构

212 阅读3分钟

Node.js是什么

  • 不是Web框架
  • 不是编程语言
  • 是一个把多种技术组合起来的一个平台,运用了V8引擎、libuv、C/C++的一些库(c-ares、http_parser) 等技术

技术架构图

image-20220228085051940.png 下面我将逐个解释重要的

bindings 绑定

C/C++实现了一个高效的http_parser库,写JS的程序员想调用这个库,直接调用肯定是不能成功的,需要一个中间的桥梁——bindings,Node.js的作者通过设计bindings模块,使JS和C/C++在数据类型上统一协调,从而顺利进行通信。

具体细节:Node.js用C++对http_parser进行封装,使它符合某些要求,封装后的文件http_parser_bindings.cpp,用Node.js提供的编译工具将其编译为.node文件。(编译成.node文件不是必须的,可以是其他的任何可行方式),这样JS代码可以直接引用这个.node文件,这样JS就能调用C++库,中间的桥梁就是binding,由于Node.js提供了很多binding,所以加个s这就是bindings。

JS和C/C++通信

  • JS调用C++函数

C++的fn.cc的库写完,编译得到fn.node文件,在test.js里调用fn里的add函数

const fn=require('./当前目录/fn');
console.log(fn.add(3,5))
  • C++回调JS函数:在C++函数里执行一个JS函数
const fn=require('./当前目录/fn');
fn((msg)=>{
  console.log(msg)
});

C/C++插件:自定义其他能力

如果C/C++没有写这个库,我们可以用C++自己写一个库作为插件,然后bindings绑定到JS上,这样JS就可以自己调用这个C++的库了,(目前前端程序员不要求)。

libuv(Node.js重要依赖之一)

每个系统(Linux/window)都有自己的异步I/O。 I/O:所有有输入/输出过程的都是I/O,系统和外界进行交互的过程,如连接打印机,上网。

libuv(简称uv)是一个跨平台的异步I/O操作,根据系统自动选择合适的方案,可以用于:

  • 操作TCP
  • 操作UDP
  • 解析DNS
  • 读写文件等异步操作。

基于此,JS可以把以上实现全部交给C/C++去做,解决I/O瓶颈,JS只负责调用即可。

V8引擎(Node.js重要依赖之二)

功能

  • 将JS源代码变成本地代码并执行
  • 引擎维护JS调用栈,确保JS函数的执行顺序
  • 内存管理,new Object时为所有对象分配内存
  • 垃圾回收,目的:重复利用无用的内存
  • 实现JS的标准库(数组的sort函数等等)

注意

  • V8不提供DOM API(document.createElement是浏览器提供的)
  • V8是线程的(内存管理,垃圾回收),但是执行JS的过程是线程的,可以开启两个线程分别执行JS
  • V8本身是包含多个线程的,如垃圾回收为单独线程
  • 自带Event Loop,但Node.js没有用它的,基于libuv 自己做了一个

总结

  • Node.js提供的标准库简化JS代码
  • Node.js用bindings让JS能和C/C++沟通:把C++的文件编译成.node文件,让JS来require
  • Node.js用C/C++库更高效处理DNS/HTTP
  • Node.js用V8运行用户写的JS
  • Node.js用libuv进行异步I/O操作(读写文件)
  • 基于libuv,Node.js自己制作了一个Event Loop用来管理事件处理顺序,先poll再check,close,timers再poll