当前位置: 首页 > 后端技术 > Node.js

node理解

时间:2023-04-03 12:41:40 Node.js

理解node.js1.nodejs诞生Node之父RyanDahl,阻塞IO是错误的方式,而V8的发布为Node的诞生打下了坚实的基础。JavaScript本身是单线程的,浏览器发起的AJAX请求是非阻塞的。因此将JavaScript与异步IO和一个简单的HTTP服务器结合起来将实现更好的合作。Node的非阻塞模型虽然没有多线程,但是却存在“回调地狱”的问题。Ryan认为Node不适合开发大型服务器端应用程序。相比之下,Go语言(运行时和操作系统之间的所有IO操作都是非阻塞的,但它提供给用户的接口是阻塞的。)会是更好的选择。参考文章:https://www.techug.com/post/n...2.nodejs简介总的来说,Node.js是一个结合了多种技术的平台,让JavaScript可以调用一些C/C++的接口,扩展了js语言的功能,让JavaScript也可以调用系统接口或进行后端开发应用。node.js工作流程:3.node.js基本架构node.js主要分为四个部分:NodeStandardLibrary,NodeBindings,V8,Libuv,架构图如下:NodeStandardLibrary是Node专门为开发者提供的使用标准库,如Http、Buffer、fs等模块。NodeBindings是JS和C++之间的桥梁,封装了V8引擎和Libuv的细节,向上层提供基础的API服务。第三层是支持Node.js运行的关键,由C/C++实现。V8是谷歌开发的JavaScript引擎,提供JavaScript运行环境。可以说是Node.js的引擎。libuv是专门为Node.js开发的封装库,提供跨平台的异步I/O能力。C-ares:提供异步DNS相关能力。http_parser、OpenSSL、zlib等:提供其他能力包括http解析、SSL、数据压缩等。4.什么是绑定?NodeBindings是JS和C++之间的桥梁,封装了V8引擎和Libuv的细节,向上层提供基础的API服务。比如:C/C++实现了一个http_parser库,效率很高,但是前端开发者只会写JavaScript,直接调用这个库肯定不会成功,所以需要一个中间桥梁。于是Node.js的作者使用C++封装了http_parser库,使其满足一定的要求(比如统一数据类型等),封装后的文件名为http_parser_bindings.cpp。同时Node.js提供的编译工具可以将其编译成.node文件。这样JavaScript代码就可以直接require这个.node文件,JavaScript就可以调用C++库了。5.为什么是libuv?Node.js首先使用了Google的V8解析引擎和MarcLehmann的libev。Node.js结合了事件驱动的I/O模型和适合这种模型的编程语言(JavaScript),但是随着Node.js的日益流行,Node.js也需要同时支持Windows,但是libev可以只能用在Unix环境下运行,Windows系统平台上kqueue(FreeBSD)或(e)poll(Linux)等内核事件通知对应的机制是IOCP。基于以上背景,Node.js之父Ryan开始开发跨平台的异步I/O库,整合以上操作系统对应的库,于是libuv诞生了,libuv将基于不同的操作systems自动选择合适的解决方案,其所有功能都是异步的,一般用于TCP/UDP/DNS/文件操作等异步操作。为什么是异步的?因为与快速CPU相比,即使SSD访问仍然是一个慢速设备。于是事件驱动IO模型应运而生,解决了高速设备同步等待慢速设备或访问的问题。这不是libuv的独创,linux内核原生支持的NIO也有这个想法。但是libuv统一了网络访问,文件访问,实现了跨平台。上面libuv的架构图从左到右分为两部分,一部分是与网络I/O相关的请求,另一部分是由文件I/O、DNSOps和Usercode组成的请求。从图中可以看出,对于NetworkI/O和另一种以FileI/O为代表的请求,异步处理的底层支持机制是完全不同的。对于NetworkI/O相关的请求,根据不同的OS平台,在Linux上使用epoll,在OSX和BSD操作系统上使用kqueue,在SunOS上使用eventports,在Windows上使用IOCP机制。对于以文件I/O为代表的请求,使用线程池。使用线程池实现异步请求处理,在各种OS上都能得到很好的支持。5、什么是V8发动机?V8是目前商业上执行JavaScript最快的引擎(它可以直接将js代码编译成二进制文件)。它有很多功能:将JavaScript源代码转换成本地代码并执行,维护JavaScript调用栈,保证JavaScript函数的执行顺序,负责内存管理,为所有对象分配内存,垃圾回收,复用无用内存,实现JS标准库。现在JS引擎的执行流程大致是:源代码--->抽象语法树--->字节码--->JIT--->原生代码。V8更直接的通过JIT技术将抽象语法树转化为本地代码,放弃了一些可以在字节码阶段进行的性能优化,但是保证了执行速度。V8在生成本地代码后,也会通过Profiler收集一些信息来优化本地代码。虽然少了生成字节码阶段的性能优化,但是转换时间大大减少了。这里有几点需要注意:V8不提供DOMAPI,DOMAPI由浏览器提供。V8本身包含多线程,但是它执行JS的过程是单线程的。V8本身有自己的Eventloop,但是Node.js基于libuv做了一个。想了解更多v8引擎的原理,可以参考:https://zhuanlan.zhihu.com/p/...自己简化一下: