当前位置:   article > 正文

详细介绍 Node.js

node.js

目录

Node.js 是什么

Node.js 能做什么

Node.js 的特点

Node.js 的组成

1) V8 引擎

2) 本地模块

3) 标准库

总结


Node.js 是什么

Node.js 不是一门新的编程语言,也不是一个 JavaScript 框架,它是一套 JavaScript 运行环境,用来支持 JavaScript 代码的执行。用编程术语来讲,Node.js 是一个 JavaScript 运行时 (Runtime),让 JavaScript 运行在浏览器之外的平台。这里的 JavaScript 并非我们在浏览器中熟悉的 JavaScript,Node.js 没有内置 DOM,也没有任何浏览器的功能。它采用事件驱动、异步编程、为网络服务而设计,实现了诸如文件系统、模块、包、操作系统 API、网络通信等 core-js 没有或者不完善的功能。

core-js 是什么:core-js 它是JavaScript标准库的 polyfill(垫片/补丁), 新功能的 es 'api' 转换为大部分现代浏览器都可以支持。

ECMAScript 的迅速成长以及浏览器的频繁更新换代,每年会出现新的 qpi,像:es6 的Promise,Set 或者 es7 数组新提供的方法 includes,这些新加入的 api,就引出一个词“polyfill“(垫片/补丁),就是社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性。新功能转换为大部分现代浏览器都可以支持运行的 api 补丁包集合。

Node.js 能做什么

  • 具有复杂逻辑的网站
  • Web 服务器
  • Web Socket 网站
  • TCP\UDP 套接字应用程序
  • 命令行工具
  • 交互式终端程序
  • 带有图形用户界面的本地应用程序
  • 客户端 Javascript 编译器
  • 单元测试工具

Node.js 的特点

Node.js 最大的特点是采用异步式 I\O 与事件驱动的架构设计。

对于高并发的解决方案,传统的架构是多线程模型,也就是为每个业务逻辑提供一个系统线程,通过系统线程切换来弥补同步式 I/O 调用时的时间开销。

Node.js 使用的是单线程模型,对于所有 I/O 都采用异步式的请求方式,避免了频繁的上下文切换。Node.js 在执行的过程中会维护一个事件队列,程序在执行时进入事件循环等待下一个事件到来,每个异步式 I/O 请求完成后会被推送到事件队列,等待程序进程进行处理。

例如,对于简单而常见的数据库查询操作,按照传统方式实现的代码如下:

  1. res = db.query('SELECT * from some_table');
  2. res.output();

以上代码在执行到第一行的时候,线程会阻塞,等待数据库返回查询结果,然后再继续处理。然而,由于数据库查询可能涉及磁盘读写和网络通信,其延时可能相当大(长达几个到几百毫秒,相比 CPU 的时钟差了好几个数量级),线程会在这里阻塞等待结果返回。对于高并发的访问,一方面线程长期阻塞等待,另一方面为了应付新请求而不断增加线程,因此会浪费大量系统资源,同时线程的增多也会占用大量的 CPU 时间来处理内存上下文切换,而且还容易遭受低速连接攻击。

 看看 Node.js 是如何解决这个问题的:

db.query('SELECT * from some_table', function(res) { res.output(); });

这段代码中 db.query 的第二个参数是一个函数,我们称为回调函数。进程在执行到 db.query 的时候,不会等待结果返回,而是直接继续执行后面的语句,直到进入事件循环。当数据库查询结果返回时,会将事件发送到事件队列,等到线程进入事件循环以后,才会调用之前的回调函数继续执行后面的逻辑。

Node.js 的异步机制是基于事件的,所有的磁盘 I/O、网络通信、数据库查询都以非阻
的方式请求,返回的结果由事件循环来处理。

Node.js 进程在同一时刻只会处理一个事件,完成后立即进入事件循环检查并处理后面的事件。这样做的好处是,CPU 和内存在同一时间集中处理一件事,同时尽可能让耗时的 I/O 操作并行执行。对于低速连接攻击,Node.js 只是在事件队列中增加请求,等待操作系统的回应,因而不会有任何多线程开销,很大程度上可以提高 Web 应用的健壮性,防止恶意攻击。

缺点:

  • 可靠性低。
  • 单进程,只支持单核CPU,不能充分的利用多核CPU服务器。一旦这个进程崩掉,那么整个web服务就崩掉了。

解决办法:

  • 开启多个进程,每个进程绑定不同的端口,用反向代理服务器。

Node.js 的组成

Node.js 运行时主要由 V8 引擎、标准库和本地模块组成,尤其是本地模块的多少,从底层决定了 Node.js 功能的强弱。

所谓运行时,就是程序在运行期间需要依赖的一系列组件或者工具;把这些工具和组件打包在一起提供给程序员,程序员就能运行自己编写的代码了。

1) V8 引擎

V8 引擎就是 JavaScript 解释器,它负责解析和执行 JavaScript 代码。JavaScript 是一种脚本语言,需要一边解释一边运行,用到哪些源代码就编译哪些源代码,整个过程由解释器完成。没有解释器的话,JavaScript 只是一堆纯文本文件,不能被计算机识别。

V8 引擎借鉴了 Java 虚拟机和 C++ 编译器的众多技术,它将 JavaScript 代码直接编译成原生机器码,并且使用了缓存机制来提高性能,这使得 JavaScript 的运行速度可以媲美二进制程序。

V8 引擎使用 C++ 语言编写,可以独立运行,也可以嵌入到任何其它 C++ 程序中。谷歌公司将 V8 引擎甚至整个 Chrome 浏览器都开源了,任何人都可以免费地将 V8 应用到自己的项目中。

2) 本地模块

所谓本地模块,就是已经被提前编译好的模块,它们是二进制文件,和可执行文件在内部结构上没有什么区别,只是不能单独运行而已。这些本地模块其实就是动态链接库(在 Windows 下是 .dll 文件),如果你使用过C语言、C++ 等编译型语言,那你应该能够更好地理解它。

本地模块一般封装了通用功能,对性能要求较高,所以通常使用编译型语言来实现,比如C语言、C++、汇编语言等。Node.js 集成了众多高性能的开源库,它们使用 C/C++ 语言实现,比如:

  • libuv:一个跨平台的、基于事件驱动的异步 I/O 库。但是 libuv 不仅限于 I/O,它还提供了进程管理、线程池、信号处理、定时器等其它功能。Linux 中一切皆文件,这里的 I/O 不仅仅包括文件读写,还包括数据库读写、网络通信(socket)等。
  • nmp:Node.js 包管理器,可以下载包、安装包、卸载包、更新包、上传包等。
  • http_parser:一款由C语言编写的轻量级 HTTP 解析器,用以支持 Web 应用开发。
  • zlib:工业级的数据压缩/解压模块,Nodejs 借助 zlib 来创建同步、异步或者流式的压缩/解压接口。
  • OpenSSL:该模块提供了经过严密测试的许多加密/解密功能,现代 Web 依赖这些功能来实现安全性,比如 SSL 协议和 https 协议。
  • c-ares:异步 DNS 查询和解析库。

Node.js 直接在计算机上运行 JavaScript 代码,并且要赋予 JavaScript 强大的能力,所以它的本地模块和浏览器中的运行时有很多大区别,甚至说几乎没有什么关联。Node.js 几乎完全抛弃了浏览器,自己从头构建了一套全新的 JavaScript 运行时。

JavaScript 解释器需要本地模块的支持,标准库在编写时也会调用本地模块的接口,而我们编写的 JavaScript 代码一般不会直接使用本地模块,所以 Web 前端程序员触及不到它们。

3) 标准库

本地模块使用 C/C++ 编写,而 Node.js 面向 JavaScript 开发人员,所以必须要封装本地模块的 C/C++ 接口,提供一套优雅的 JavaScript 接口给开发人员,并且要保持接口在不同平台(操作系统)上的一致性。

这套 JavaScript 接口,就是 Node.js 标准库。标准库是否优雅和强大,决定了 Node.js 的易用性,直接影响 Node.js 的市场表现。

总结

解释器、标准库、本地模块等各种组件/工具共同支撑了 JavaScript 代码的运行,它们统称为 JavaScript 运行时。

在 Node.js 之前,JavaScript 运行时被绑定在浏览器中,作为浏览器的各种模块出现。这意味着,要想运行 JavaScript 代码就必须启动浏览器,JavaScript 逃不出浏览器的手掌心,它的功能受到很大的限制,只能作为网页脚本使用。

V8 引擎和众多本地模块都是现成的,别人已经造好了轮子,Node.js 的主要工作就是选择合适的模块,将它们集成在一起,并编写好 JavaScript 接口。

当然,并不是所有的本地模块都能找到合适的,Node.js 也自己编写了几个模块,典型的代表就是 Libuv。Libuv 是 Node.js 最核心最基础的模块,Node.js 完全基于 Libuv 而构建。

Node.js 采用了基于事件的、单线程的异步 I/O 架构,这是 Node.js 最大的特点,也是它和其它脚本语言最大的区别,Node.js 的这种能力就是依赖 Libuv 实现的。

 Libuv 如此强大,官方决定将它从 Node.js 中剥离出来,作为一个单独的网络库发布,并且开源免费。现在的 Libuv 已经变得非常流行,和传统的 Libevent 和 libev 库并称为 “C/C++  三大网络库”。

Node.js 是一个 JavaScript 运行时,它让 JavaScript 脱离了浏览器环境,可以直接在计算机上运行,极大地拓展了 JavaScript 用途。我们应该将 JavaScript 和 Python、Java、Ruby 等其它编程语言同等对待,不能再将它视为一种 “小玩意”。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/174367
推荐阅读
相关标签
  

闽ICP备14008679号