学习掌握范围
1、掌握Nodejs模块机制及原理 | 2、掌握Nodejs网络编程能力 | 3、掌握Nodejs进程管理能力 |
1、Nodejs模块机制 - CommonJS
模块引用 | 通过require(module)来引入module |
模块定义 | 通过挂载在module.exports对象上实现定义 |
模块标识 | 通过路径标识引入的是哪个模块 |
引入一个模块经历的四个过程:路径分析 --> 文件定位 --> 编译执行 --> 加入缓存
内置模块 |
- 在Node进程开始的时候就预加载了 - 加载的是二进制文件,无需定位和编译 |
文件模块 |
- 通过NPM安装的第三方模块 - 本地模块 |
模块内容 | - 函数、对象或者属性,如函数、数组甚至任意类型的JS对象 |
模块加载的优先级:已缓存模块 --> 内置模块 --> 文件模块 --> 文件目录模块 --> node_modules模块
模块编译执行
.js文件 | - 通过fs模块同步读取侯编译执行,未识别类型也会当作js处理 |
.json文件 | - 通过fs模块同步读取后,用JSON.parse()解析闭关返回结果 |
.node文件 | - 通过C/C++写的扩展文件,通过process.dlopen()方法加载最后编译生成的 |
模块js文件的编译
注入全局变量 |
- 以参数形式,注入module/exports/require方法 - 同时注入路径解析得到的__filename/__dirname |
构造上下文执行环境 |
- 闭包产生作用域,通过runInThisContext()执行 - 将function对象挂载到exports对象上,并导出 |
加入缓存以及清除缓存
核心模块 | - 登记在NativeModule._cache上 |
文件模块 | - 封装后的方法以字符串的形式存储,等待调用 |
清除缓存 | - 通过delete require.cache[require.resolve(module)] |
require vs import
import | require |
- Es6的规范 - 静态加载模块 - 编译的时候执行代码 - 缓存执行结果 - 按需引入,节省内存 |
- common JS规范 - 动态加载模块 - 调用的时候加载源码 - 加载全部代码 |
2、Nodejs的网络编程能力
Nodejs网络基础模块 - net / dgram
- net 模块是TCP/IP的Node实现,提供了一些用于底层的网络通信的小工具 |
- http.Server继承自net.Server |
- http客户端与http服务端的通信均依赖于socket(net.Socket) - net.Server: TCP server,内部通过socket来实现与客户端的通信 - net.Socket:本地socket的node版实现,是对TCP或UNIX Socket的抽象,它实现了全双工的stream接口, Api归纳:-连接相关connect -数据读写write -数据属性bufferSize -地址相关address |
动手写一个感受下: - 服务器A启动服务,等待连接 - 基于事件驱动,服务器B访问服务器A提供的服务 - 关闭数据请求,结束服务 service A <-------socket-------> service B
|
Nodejs的网络编程 - http / https / http2
- HTTP 模块是Node的门脸,是编写Web Server最常见的模块 |
- Server 部分继承自 net.Server,并对请求和相应数据进行了封装 |
- 也提供了 request/get 能力,允许向其他服务端发起HTTP请求 |
- Node封装了 HTTPS/HTTP2 的实现,可以轻松创建类HTTP服务 |
3、Nodejs的进程管理
问题:1、Nodejs是单线程的程序吗? 2、耗时计算,怎么避免阻塞? 3、如何实现多进程的开启和关闭? 4、如何实现多线程? 5、怎么做的进程守护?
操作系统的进程与线程
- 运行任务的程序叫做“进程”,一个进程只能执行一个任务 |
- 进程并发:以多进程形式,允许多个任务同时进行, (进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础) |
- 线程并发:以多线程形式,允许单个任务分成不同的部分运行 (线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务) |
- 操作系统提供协调机制,防止冲突,共享资源 |
- JavaScript是单线程语言,所以多个任务之恶能排队进行 |
EventLoop
- 同步(阻塞)调度 |
- 异步(非阻塞)调度 |
- js通过EventLoop的形式解决单线程任务调度问题 |
- EventLoop是一个程序结构,用于等待和发送消息和事件 |
- 浏览器的Event Loop和Node的EventLoop是两个概念
|
Node进程管理模块
process |
- process是一个全局对象,无需require直接使用,提供进程描述 - process对象是一个 EventEmiter 的实例,暴露了进程事件的钩子 - exit 今天进程退出 - uncaughtException 监听异常 - 提供标准流输出,对应的是进程的 I/O 操作 - node版本的console底层是由stdio实现的 - 数据流与其他双工数据流不同,同步写会阻塞进程导致性能开销 |
child_process |
- child_process是Nodejs的内置模块 - spawn:适用于返回大量数据,例如图像处理,二进制数据处理 - exec:适用于小量数据,maxBuffer默认值为200*1024超出崩溃 - fork:衍生新的进程,进程之间是相互独立的,每个进程独立 |
cluster |
- cluster是Node.js的内置模块 - Worker对象:包含了关于工作进程的所有的公共的信息和方法 - fork:衍生新的进程,进程之间是相互独立的,每个进程独立 - 使用主从模型轮询处理服务的负载任务,通过IPC通信 |
进程守护
使用工具实现进程守护 pm2 / forever |