进程管理API简介
process:进程对象,提供标准输入、输出、运行权限、运行环境和状态等信息child_process:创建和管理子进程- 核心方法:
spawn() - 其他方法都是对spawn进行封装的语法糖:
fork | exec | execFile
- 核心方法:
cluster:对child_process的进一步补充,实现多进程- 专用于解决单进程
NodeJS Web服务器无法充分利用多核CPU的问题。 - 用于简化多进程服务程序的开发。
- 专用于解决单进程
woker_threads:多线程能力- 可以共享内存,通过传输
ArrayBuffer实例,或共享SharedArrayBuffer实例实现 - Worker:在主线程中创建子线程,接收
fileName作为参数,为子线程执行的入口
- 可以共享内存,通过传输
process
事件类型
- message:监听IPC通道,衍生的Node.js子进程,用send()发送的消息
- beforeExit:不要将beforeExit作为exit的替代事件
- exit: 调用exit()方法时,会触发
- disconnect:IPC通道被关闭时,
- warning:进程触发警告
- 错误类型的事件监听:
unhandleRejection | uncaughtException | uncaughtExceptionMonitor - 信号事件:一般用于和系统通信,包括多种类型的事件,如SIGINT | SIGTERM等
- 信号事件,在
Worker线程上不可用
- 信号事件,在
方法:
abort | exit | disconnect | kill | getuid | setuig | getgid | setgid
退出程序
- 正常退出码是0
- 异常退出有多种状态码:1 | 3 | 4 | 5 | 6 | 7 | 9 | 10
console
- console.log()
- cosole.error():输出错误
- console.trace():向标准错误流输出当前的调用栈
process.nextTick()
- 在同步事件执行完成之后,就会触发,是在本轮循环执行的
- 将大事件拆分为小事件,减少每个事件的执行时间,提高事件响应速度
- 引入的原因:Node是单线程,如果某个事件占用大量的CPU时间,就会造成页面卡顿,所以用nextTick()缩短每个事件的执行时间
- 不要用setTimeout()代替nextTick,因为setTimeout的效率要低很多
常用API
- process.argv可以获得命令行参数
argv[0] == NodeJS执行程序的绝对路径argv[1]: 主模块的绝对路径argv[2]:第一个命令行参数从这个位置开始
// 获取process命令行命令
process.argv.slice(2)
- process.stdin:标准输入数据流,只读
- Process.stdout:只写
- processs.stderr:只写
- process.channel:如果该进程是由IPC通道创建的,则该属性保存IPC通道的引用,
- process.title:进程名称
- pid:进程ID、ppid:父进程ID
- platform:操作系统平台
- process.updatetime():当前进程已运行时间
- 如何降权???gid \ uid属性
- 有root权限,才能监听1024以下的端口;完成监听的操作后,最好把权限降下来
- process.setuid:设置用户标识
- process.setgid:为进程设置组标识
- 获取当前uid,或gid
- process.env.SUDO_UID || SUDO_GID
- process.getuid() | process.getgid()
- 有root权限,才能监听1024以下的端口;完成监听的操作后,最好把权限降下来
child_process
简介
- 用于创建子进程。
- 创建子进程后,会在父子进程的管道间,创建数据流 stdin | stdout | stderr
- 可以创建异步进程(spawn | fork | exec | execFile)
- 也可以创建同步进程(spawnSync、execSync、execFileSync)
- 同步/异步进程,方法都会返回ChildProcess实例
ChildProcess类
- 提供的事件
- close | disconnect | exit | error | message | close
- close事件和exit事件不同
- 当子进程的stdio流被关闭时会触发close
- 但当exit事件被触发时,子进程的stdio流可能依然是打开的
- 属性:
- channel | connected | exitCode
- 常用方法:send() | kill()
常用API
- child_process.spawn(command, args, options)
- 返回ChildProcess类的实例,
- 可在options中,指定衍生子进程的工作目录和环境变量
- child_process.exec(command, options, callback)
- 用node的子进程运行命令command,command是一个字符串
- options是一个对象,包含cwd\env\stdio等
- 会先创建一个shell,然后在shell中运行命令,命令执行结束后,会将stdout/stderr返回
- child_process.execFile()
- 直接执行命令,而不先衍生一个shell
- child_process.fork(modulePath, args, options)
- modulePath:要在子进程中运行的模块,只能运行node子进程
- Fork是spawn的特殊形式,但是它会在父进程和子进程中间建立一个管道用于消息传递
- 衍生的node.js进程独立于父进程,除了IPC可以通信外,每个进程都有自己的内存,带着自己的V8实例,返回自己的childProcess对象
- 由于需要额外的资源分配,因此不建议衍生大量的Node.js进程
- 衍生的进程数量,最多可以和cpu数量相等
require(‘os’).cpus():返回一个对象数组,获取核数
- maBuffer:指定 stderr和stdout上允许的最大字节数,超过该字节数时,进程会被终止。
exec和execFile的区别
- execFile,适用于Mac\unix\linux等系统。因为它直接运行,因此更高效
- exec,适用于windows系统,因为.bat, .cmd文件无法直接执行命令,必须借助于shell
主进程和子进程通信
cluster
系统进程架构类型
- 单进程多线程
- 优点:线程间切换的开销比较小
- 缺点:稳定性不高。线程数量会受到内存的限制,当线程达到一定数量后,增加cpu也不能提升性能
- 单线程多进程
- 优点:高性能,不用频繁的切换线程。高并发时,也可以保持低内存的占用。可以根据cpu的数量增加进程数;线程安全,不用添加锁的机制;异步非阻塞
- 缺点:进程间的调度开销大,跨进程通信传输的数据不能太大。
简介
- cluster可以创建共享服务器端口的不同子进程
- 工作进程由child_process.fork()创建,因此可以使用IPC和父进程进行通信,所以可以使各个进程交替处理连接服务
实现原理
- 轮询(除windows外的默认方法):主进程监听端口
- 主进程创建socket,发送给感兴趣的子进程,但由于操作系统调度机制的难以琢磨,分发变得很不稳定,可能会出现分配不均的情况
- 注意:Node.js不支持路由逻辑;各个工作进程间是相互独立的,他们的关闭或打开不会影响其他进程。
工作进程属性--Worker类
- 如何获取
- 在主进程中获取:cluster.workers
- 在工作进程中读取:cluster.worker
- 事件:disconnect | exit | online | listening | message | error
- 方法:disconnect | kill | send | isConnected
- 属性:id | process(process属性即上节中讲到的 process类,包含pid | ppid | env 等属性)
事件类型分类
- 备注:以下事件的回调函数中,第一个参数都是Worker类
- 连接:
- fork:衍生出一个新的工作进程后,会自动触发该事件
- online:
- 当一个新的进程被衍生时,会触发fork事件,但等到工作进程被运行的时候会触发online响应事件
- setup:setupMaster后被触发,setupMaster方法用于重置fork的配置
- 退出:
- disconnect(callback):工作进程的IPC通道被断开后悔被触发
- exit事件
- 任何一个工作进程关闭的时候,都会触发
- 可以用于重启工作进程
- 备注:disconnect和exit事件之间,可能会存在延迟
- 消息监听
- listening
- 工作进程调用listen后,工作进程上的server会触发listening, cluster.listening也会被触发
- message
- 主进程接收到任意工作进程的消息后,都会被触发
- listening
属性配置:
- setupMaster
- 修改fork的默认行为,一旦被调用后,将会按照settings设置,该方法只对后面的fork()起作用,对前面已经fork的进程不起作用
- isMaster:是否是主类
- isWorker:是否是工作进程
- worker
- 当前工作进程的引用,对主进程无效
- 在工作进程中,可用cluster.worker获取
- workers:哈希表,存储活跃的所有工作进程对象
- 在主进程中,可用cluster.workers获取所有子进程,id是键名,可以很方便的遍历子进程
- settings
- Fork()后,或setupMaster()后,工作进程的一些默认值
- schedulingPolicy
- 调度策略