关于 Process, 我们需要讨论的是两个概念, ①操作系统的进程, ② Node.js 中的 Process 对象. 操作进程对于服务端而言, 好比 html 之于前端一样基础. 想做服务端编程是不可能绕过 Unix/Linux 的. 在 Linux/Unix/Mac 系统中运行 ps -ef 命令可以看到当前系统中运行的进程. 各个参数如下:
常见api
Node.js 中的 process 对象. 直接在代码中通过 console.log(process) 即可打印出来. 可以看到 process 对象暴露了非常多有用的属性以及方法, 具体的细节见官方文档, 已经说的挺详细了. 其中包括但不限于:
- 进程基础信息
- 进程 Usage
- 进程级事件
- 依赖模块/版本信息
- OS 基础信息
- 账户信息
- 信号收发
- 三个标准流
官方文档: https://nodejs.org/api/proces...
process
是一个 global
全局对象
提供有关信息,控制当前 Node.js 进程。作为一个对象,它对于 Node.js 应用程序始终是可用的,故无需使用 require()
。
process 这个对象是EventEmitter
的实例。
process.env.NODE_PATH
获取到在系统中环境变量设置的内容:
__dirname:获取到当前文件所在的路径:
process.nextTick
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
process.nextTick 并不属于 Event loop 中的某一个阶段, 而是在 Event loop 的每一个阶段结束后, 直接执行 nextTickQueue 中插入的 "Tick", 并且直到整个 Queue 处理完.
具体的api照着文档看
标准输入输出流
在 process 对象上还暴露了 process.stderr, process.stdout 以及 process.stdin 三个标准流, 熟悉 C/C++/Java 的同学应该对此比较熟悉.
console.log 是同步还是异步?
console.log既不是总是同步的,也不总是异步的。是否为同步取决于链接的是什么流以及操作系统是Windows还是POSIX:
注意: 同步写将会阻塞事件循环直到写完成。 有时可能一瞬间就能写到一个文件,但当系统处于高负载时,管道的接收端可能不会被读取、缓慢的终端或文件系统,因为事件循环被阻塞的足够频繁且足够长的时间,这些可能会给系统性能带来消极的影响。当你向一个交互终端会话写时这可能不是个问题,但当生产日志到进程的输出流时要特别留心。
- 文件(Files): Windows和POSIX平台下都是同步
- 终端(TTYs): 在Windows平台下同步,在POSIX平台下异步
- 管道(Pipes): 在Windows平台下同步,在POSIX平台下异步
如何实现一个 console.log?
实现console.log在控制台打印,利用process.stdout将输入流数据输出到输出流(即输出到终端),一个简单的例子输出hello world process.stdout.write('hello world!' + 'n');,以下例子是对console源码解读实现,将Console取名为Logger。
https://www.imooc.com/article...
A note on process I/O
这里来做个计算器实例:
跨系统
node.js提供了 os.platform() 或者 process.platform 来检测当前系统
os.platform 或 process.platform 返回
'darwin', 'freebsd', 'linux', 'sunos' or 'win32'
[多进程架构]
Node 的线程池
在 Node 中有一些 IO 操作(DNS,FS)和一些 CPU 密集计算(Zlib,Crypto)会启用 Node 的线程池,而线程池默认大小为 4
手动更改线程池默认大小:
process.env.UV_THREADPOOL_SIZE = 64
cluster
cluster 是多线程吗?
Node 的单线程也带来了一些问题,比如对 cpu 利用不足,某个未捕获的异常可能会导致整个程序的退出等等。因为 Node 中提供了 cluster 模块,cluster 实现了对 child_process 的封装,通过 fork 方法创建子进程的方式实现了多进程模型。比如我们最常用到的 pm2 就是其中最优秀的代表。
一共有 9 个进程,其中一个主进程,cpu 个数 x cpu 核数 = 2 x 4 = 8 个 子进程。 numCPUs = 8
所以无论 child_process 还是 cluster,都不是多线程模型,而是多进程模型。虽然开发者意识到了单线程模型的问题,但是没有从根本上解决问题,而且提供了一个多进程的方式来模拟多线程。从前面的实验可以看出,虽然 Node (V8)本身是具有多线程的能力的,但是开发者并不能很好的利用这个能力,更多的是由 Node 底层提供的一些方式来使用多线程。Node 官方说:
You can use the built-in Node Worker Pool by developing a C++ addon. On older versions of Node, build your C++ addon using NAN, and on newer versions use N-API. node-webworker-threads offers a JavaScript-only way to access Node’s Worker Pool.
Node 10.5.0
的发布之前, 对于 JavaScript 开发者,一直没有一个标准的、好用的方式
来使用 Node 的多线程能力。
worker_threads
Node 10.5.0 的发布,官方才给出了一个实验性质的模块 worker_threads 给 Node 提供真正的多线程能力。
jin
参考:
Node.js的进程管理:https://segmentfault.com/a/11...
饿了么 process
真-Node多线程