简介
后台任务模块。提供子进程任务管理和负载均衡能力,在 Electron 主进程之外运行任务。
重要
所有 Electron 相关 API 不能在子进程中使用。
核心组件:
- ChildJob:单任务执行,每次创建新的子进程。按需获取,完成即释放。适用于不频繁的任务。频繁大量创建任务时有进程启动开销——此时应使用 ChildPoolJob。
- ChildPoolJob:进程池,维护常驻子进程,通过负载均衡复用。避免频繁创建销毁进程的开销。
- LoadBalancer:负载均衡器,支持 8 种调度算法在进程间分配任务。
- AlgorithmType:算法类型常量。
- Registry:
registerJobManager()/killAllJobs()用于应用退出时集中清理。
导入
CJS 和 ESM:
// ESM
import { ChildJob, ChildPoolJob, LoadBalancer, AlgorithmType } from 'ee-core/jobs';
import type { LoadBalancerTarget, LoadBalancerParams, LoadBalancerOptions } from 'ee-core/jobs';
import type { JobProcessOptions, JobMessage, ProcessMessage } from 'ee-core/jobs';
import type { ChildPoolOptions } from 'ee-core/jobs';
// CJS
const { ChildJob, ChildPoolJob, LoadBalancer, AlgorithmType } = require('ee-core/jobs');ChildJob
简介
单任务子进程管理器。每次 exec() 调用创建一个新的 child_process.fork()。子进程任务完成后必须调用 Ps.exit() 终止,否则会持续运行浪费资源。
优点:按需获取,完成即释放,不会过度占用计算机资源。
局限:频繁大量创建任务时有进程启动开销。此场景应使用 ChildPoolJob。
用法
import { ChildJob } from 'ee-core/jobs';
const job = new ChildJob();API
job.jobs
说明:属性。以 PID 为键的活动 JobProcess 实例集合。进程退出或出错时自动移除。 返回值:Record<number, JobProcess>
job.exec(filepath, params, opt)
说明:启动新的子进程执行任务文件。通过 getFullpath() 将 filepath 解析为绝对路径,创建 JobProcess,并分发 run 命令。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| filepath | string | 是 | ./jobs 目录的相对路径,或绝对路径 |
| params | Record<string, unknown> | 否 | 传递给任务的参数 |
| opt | JobProcessOptions | 否 | 进程选项(processArgs、processOptions) |
返回值:JobProcess — 子进程实例 示例:
const myProc = job.exec('./jobs/example/timer', { jobId: 'task-1' });job.execPromise(filepath, params, opt)
说明:exec() 的异步语法版本。创建新的子进程执行任务文件。返回与 exec() 相同的 JobProcess。 参数:与 exec() 相同 返回值:Promise<JobProcess> — 子进程实例 示例:
job.execPromise('./jobs/example/timer', { jobId }).then(task => {
const eventName = 'job-timer-progress-' + jobId;
task.emitter.on(eventName, (data) => {
// 处理进度
});
});job.createProcess(opt)
说明:创建 JobProcess 实例但不分发命令。适用于需要子进程但想稍后手动发送命令的场景。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| opt | JobProcessOptions | 否 | 进程选项(processArgs、processOptions) |
返回值:JobProcess — 新创建的进程实例
job.getPids()
说明:获取所有活动子进程的 PID 列表。 参数:无 返回值:string[] — PID 字符串数组
job.on(eventName, callback)
说明:监听子进程发出的事件。ChildJob 继承自 EventEmitter。注意:多个子进程同时存在时可能难以区分来源——使用 JobProcess.emitter 获取每进程事件。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| eventName | string | 是 | 事件名 |
| callback | Function | 是 | 事件处理函数 |
示例:
// 在服务中:./electron/service/example.js
const eventName = 'job-timer-progress-' + jobId;
job.on(eventName, (data) => {
// 处理来自子进程的数据
});
// 在任务中:./electron/jobs/timer.js
import { childMessage } from 'ee-core/message';
const eventName = 'job-timer-progress-' + jobId;
childMessage.sendToMain(eventName, { jobId, number });JobProcess(实体)
由 exec()、execPromise() 或 createProcess() 返回的进程对象。
myProc.emitter
说明:每进程(forkProcess 级别)事件的 EventEmitter 实例。来自子进程的 eventReceiver: 'forkProcess' 消息在此发射。 返回值:EventEmitter
myProc.child
说明:由 child_process.fork() 返回的 ChildProcess 对象。参见 Node.js child_process 文档。 返回值:ChildProcess
myProc.pid
说明:子进程 PID。 返回值:number | undefined
myProc.dispatch(cmd, jobPath, ...params)
说明:向子进程发送分发消息。生成唯一消息 ID 并发送 JobMessage。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cmd | string | 是 | 命令(如 'run') |
| jobPath | string | 否 | 任务文件路径(默认 '') |
| params | unknown[] | 否 | 额外参数 |
返回值:void
myProc.callFunc(jobPath, funcName, ...params)
说明:调用子进程中任务实例的指定方法。将任务文件路径解析为绝对路径并发送带 jobFunc 和 jobFuncParams 的 run 命令。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| jobPath | string | 否 | 任务文件路径(相对路径解析为绝对路径) |
| funcName | string | 否 | 要调用的任务实例方法名 |
| params | unknown[] | 否 | 方法参数 |
返回值:void示例:
myProc.callFunc('./jobs/example/timer', 'pause', param1, param2);myProc.kill(timeout)
说明:终止子进程。先发送 SIGINT 优雅退出,超时后发送 SIGKILL 强制终止。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timeout | number | 否 | 等待优雅退出的超时时间(毫秒,默认:1000) |
返回值:void
ChildPoolJob
简介
子进程池管理器。维护一组常驻子进程,通过 LoadBalancer 分配任务。避免频繁创建销毁进程的开销。
- 池大小:最小=3,最大=6(可配置)
- 负载均衡:支持多种算法,默认为
polling(轮询) - 进程绑定:通过
boundMap将特定 ID 绑定到固定进程(如会话绑定) - 自动清理:子进程退出/出错时自动从池中移除
用法
import { ChildPoolJob } from 'ee-core/jobs';
const pool = new ChildPoolJob();
await pool.create(3); // 创建 3 个子进程构造函数
new ChildPoolJob(opt?)| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| opt | ChildPoolOptions | 否 | 池选项 |
ChildPoolOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| weights | number[] | 否 | 每个进程的权重值(用于加权负载均衡算法) |
API
pool.children
说明:属性。以 PID 为键的活动 JobProcess 实例集合。 返回值:Record<number, JobProcess>
pool.boundMap
说明:属性。绑定映射,将 boundId 映射到 PID。确保同一 boundId 总是分配到同一子进程(如会话绑定)。 返回值:Map<string | number, number>
pool.min
说明:属性。池中最小进程数(默认:3)。 返回值:number
pool.max
说明:属性。池中最大进程数(默认:6)。 返回值:number
pool.strategy
说明:属性。当前负载均衡策略名(默认:'polling')。 返回值:string
pool.weights
说明:属性。每个进程位置的权重数组。默认权重为 1;可通过构造函数选项自定义。 返回值:number[]
pool.LB
说明:属性。用于进程选择的 LoadBalancer 实例。 返回值:LoadBalancer
pool.create(number)
说明:创建指定数量的子进程并添加到池和负载均衡器。数量受 max 限制;超出部分不会创建。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| number | number | 否 | 要创建的进程数(默认:3) |
返回值:Promise<string[]> — 创建后所有进程 PID 列表 示例:
pool.create(3).then(pids => {
// pids: ['12345', '12346', '12347']
});pool.run(filepath, params)
说明:通过负载均衡器从池中选择子进程并执行任务文件。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| filepath | string | 是 | ./jobs 目录的相对路径,或绝对路径 |
| params | Record<string, unknown> | 否 | 传递给任务的参数 |
返回值:Promise<JobProcess> — 执行任务的子进程实例 示例:
const timerTask = await pool.run('./jobs/example/timer', { jobId });pool.runPromise(filepath, params)
说明:run() 的别名。通过池执行任务文件的异步语法。 参数:与 run() 相同 返回值:Promise<JobProcess>
pool.getBoundChild(boundId)
说明:获取绑定到特定 ID 的子进程。同一 boundId 总是返回同一进程,适用于会话绑定场景。如果绑定的进程不再存在,则重新分配并更新绑定。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| boundId | `string | number` | 是 |
返回值:Promise<JobProcess> — 绑定的子进程实例
pool.getChildByPid(pid)
说明:按 PID 获取子进程。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| pid | number | 是 | 进程 ID |
返回值:JobProcess | null
pool.getChild()
说明:从池中获取可用子进程。如果池为空,自动创建一个。使用负载均衡器选择进程。 参数:无 返回值:Promise<JobProcess> — 选中的子进程实例
pool.getPids()
说明:获取池中所有子进程的 PID 列表。 参数:无 返回值:string[] — PID 字符串数组
pool.killAll(type)
说明:终止池中所有子进程。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| type | `'parallel' | 'sequence'` | 否 |
返回值:void
pool.on(eventName, callback)
说明:监听池级事件。ChildPoolJob 继承自 EventEmitter。每进程事件请使用 JobProcess.emitter。
JobProcess(实体)
与 ChildJob 部分描述的实体相同。由 run()、runPromise()、getBoundChild()、getChild() 返回。
LoadBalancer
简介
负载均衡器,在子进程间分配任务。支持 8 种调度算法。基于 electron-re 项目并做了修改。
用法
import { LoadBalancer, AlgorithmType } from 'ee-core/jobs';
const lb = new LoadBalancer({
targets: [{ id: 1, weight: 1 }, { id: 2, weight: 2 }],
algorithm: AlgorithmType.polling,
});构造函数
new LoadBalancer(options)| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| options | LoadBalancerOptions | 是 | 配置选项 |
| options.targets | LoadBalancerTarget[] | 是 | 目标列表 [{id, weight}] |
| options.algorithm | string | 否 | 算法名(默认:AlgorithmType.polling) |
LoadBalancerTarget:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | `string | number` | 是 |
| weight | number | 否 | 权重值(用于加权算法) |
LoadBalancerOptions:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| targets | LoadBalancerTarget[] | 是 | 目标列表 |
| algorithm | string | 否 | 算法名(默认:'polling') |
API
LoadBalancer.Algorithm
说明:静态属性。AlgorithmType 常量对象的引用,便于访问算法名。 返回值:AlgorithmType
lb.pickOne(...params)
说明:使用配置的算法选举单个目标进程。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| params | unknown[] | 否 | 算法的额外参数(如 specify 算法需要 ID) |
返回值:LoadBalancerTarget | null — 选中的目标,无可用目标时返回 null
lb.pickMulti(count, ...params)
说明:通过重复调用 pickOne() 选举多个目标进程。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| count | number | 否 | 要选择的目标数(默认:1) |
| params | unknown[] | 否 | 传递给每次 pickOne() 调用的额外参数 |
返回值:(LoadBalancerTarget | null)[] — 选中的目标数组
lb.add(task)
说明:向负载均衡器添加目标。如果目标 ID 已存在,记录警告并无操作。添加后重新计算权重总和。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| task | LoadBalancerTarget | 是 | 要添加的目标 {id, weight} |
返回值:void
lb.del(target)
说明:从负载均衡器删除目标。从目标列表移除,清理连接/占用映射,重新计算索引和权重。如果目标 ID 未找到,记录警告。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| target | LoadBalancerTarget | 是 | 要删除的目标 {id, weight} |
返回值:void
lb.wipe()
说明:移除所有目标并重置所有内部状态(连接、占用映射、索引)。 参数:无 返回值:void
lb.setTargets(targets)
说明:替换整个目标列表。清理不在新列表中的目标状态。重新计算权重总和。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| targets | LoadBalancerTarget[] | 是 | 新目标列表 |
返回值:void
lb.setAlgorithm(algorithm)
说明:更改调度算法。重置权重索引。如果算法名不在 AlgorithmType 中则抛出错误。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| algorithm | string | 是 | AlgorithmType 中的算法名 |
返回值:void示例:
lb.setAlgorithm(AlgorithmType.weightsPolling);lb.refreshParams(pidMap)
说明:从进程信息刷新 CPU 和内存占用数据。用于最小连接数和加权最小连接数算法。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| pidMap | `Record<string | number, PidInfo>` | 是 |
PidInfo:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| pid | `string | number` | 是 |
| cpu | number | 是 | CPU 使用率 |
| memory | number | 是 | 内存使用率 |
返回值:void
lb.updateParams(object)
说明:更新特定负载均衡器运行参数(currentIndex、weightIndex、weightTotal、connectionsMap 等)。仅更新 LoadBalancerParams 中存在的键。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| object | Partial<LoadBalancerParams> | 是 | 要更新的参数 |
返回值:void
lb.clean(id)
说明:清理内部状态。如果提供 id,移除该特定目标的连接/占用数据。如果不提供 id,重置所有内部映射但保留权重总和。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | `string | number` | 否 |
返回值:void
常量
AlgorithmType
说明:负载均衡算法类型常量。用于配置 LoadBalancer 算法和 ChildPoolJob 策略。
| 常量 | 值 | 说明 |
|---|---|---|
AlgorithmType.polling | 'polling' | 轮询:按顺序选择下一个目标 |
AlgorithmType.weights | 'weights' | 加权:按权重比例选择 |
AlgorithmType.random | 'random' | 随机:随机选择目标 |
AlgorithmType.specify | 'specify' | 指定:按 ID 选择目标(需要 id 参数) |
AlgorithmType.weightsPolling | 'weightsPolling' | 加权轮询:结合权重和顺序选择 |
AlgorithmType.weightsRandom | 'weightsRandom' | 加权随机:结合权重和随机选择 |
AlgorithmType.minimumConnection | 'minimumConnection' | 最小连接数:选择当前连接数最少的目标 |
AlgorithmType.weightsMinimumConnection | 'weightsMinimumConnection' | 加权最小连接数:结合权重和最小连接数 |
示例:
import { AlgorithmType } from 'ee-core/jobs';
// 在 LoadBalancer 中使用
const lb = new LoadBalancer({
targets: [{ id: 1, weight: 2 }, { id: 2, weight: 1 }],
algorithm: AlgorithmType.weightsPolling,
});
// 在 ChildPoolJob 中使用
const pool = new ChildPoolJob({ weights: [2, 1, 1] });
pool.LB.setAlgorithm(AlgorithmType.weightsRandom);Registry
registerJobManager(job)
说明:注册任务管理器实例(ChildJob 或 ChildPoolJob)用于集中清理。在创建 ChildJob 或 ChildPoolJob 后调用,确保应用退出时所有子进程被正确终止。 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| job | Killable | 是 | 任务管理器实例(必须有 killAll() 方法,或 getPids() + kill() 方法) |
返回值:void示例:
import { ChildJob, registerJobManager } from 'ee-core/jobs';
const job = new ChildJob();
registerJobManager(job);killAllJobs()
说明:终止所有注册的任务管理器。在 Electron before-quit 事件中调用,确保所有子进程被正确终止,防止进程泄漏。优先使用 killAll() 方法;回退到通过 getPids() + kill() 逐个终止进程。 参数:无 返回值:void示例:
import { killAllJobs } from 'ee-core/jobs';
// 在应用退出生命周期中调用
killAllJobs();参见:通过 before-quit 事件在框架生命周期中自动注册
类型
JobProcessOptions
创建 JobProcess 时的选项。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| processArgs | Record<string, unknown> | 否 | 传递给子进程的参数对象 |
| processOptions | ForkOptions | 否 | Fork 选项(cwd、env、stdio 等) |
JobMessage
消息格式:主进程 → 子进程。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息 ID(随机字符串) |
| cmd | string | 是 | 命令(如 'run') |
| jobPath | string | 否 | 任务文件路径 |
| jobParams | unknown[] | 否 | 任务构造函数参数 |
| jobFunc | string | 否 | 要调用的实例方法名 |
| jobFuncParams | unknown[] | 否 | 实例方法参数 |
ProcessMessage
消息格式:子进程 → 主进程。扩展 MessageData。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| eventReceiver | string | 是 | 消息接收者类型:'forkProcess'、'childJob' 或 'all' |
| event | string | 是 | 事件名 |
| data | unknown | 否 | 事件数据 |
LoadBalancerParams
负载均衡器运行参数。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| currentIndex | number | 是 | 当前轮询索引 |
| weightIndex | number | 是 | 当前权重索引(用于加权轮询) |
| weightTotal | number | 是 | 所有权重之和 |
| connectionsMap | `Record<string | number, number>` | 是 |
| cpuOccupancyMap | `Record<string | number, number>` | 是 |
| memoryOccupancyMap | `Record<string | number, number>` | 是 |
