0.0.3 • Published 2 years ago
poolove v0.0.3
poolove
使用 fastify
和 piscina
将您的 Node.js 利用 worker_threads
进行任务派发.
起因
在一个生产实例中,我们有一台机器启动了大概 17 个 Cluster, 使用 pm2;这导致于空闲状态下也会有 2.5GB 的 node 内存开销,Cluster 的内存复用率极低,并且它配合 pm2 无法根据请求量弹性的调整集群数量。
如果仅仅启动若干个 Cluster,生产机器的多核 CPU 利用率无法上去。
目标
- 解决空闲时开满 Cluster 导致的内存开销
- I/O 密集和 CPU 密集混合场景下,达到和开满 Cluster 接近的性能
- 自带一套极简的性能监控功能(未来目标)
Performace
诚然,使用事件循环明显比使用线程有着更高的 I/O 性能, 所以使用此方案在纯 I/O 密集任务会有所下降,但是依然保持在一个非常高的水准;而在计算密集型的场景,性能接近于 全量 CPU 的 Cluster 启动。
相较启动大量 Cluster,poolove 的内存占用率会大幅度下降,但是相较于仅仅启动一个 nodejs 进程,poolver 有接近两倍的开销。
以下是一些测试数据,测试 CPU: Apple M1 pro
简单请求
对于极简的请求,事件轮训是最高效的,Cluster 、worker_threads 都有一定的分流开销
方案 | QPS | MEM |
---|---|---|
node index.js | 22889 | 70 MB |
pm2 start index.js -i 10 | 20844 | 650 MB |
poolove worker.js | 14651 | 160 MB |
查询数据库,I/O 密集型
从一个小表中查询几条数据
方案 | QPS | MEM |
---|---|---|
node index.js | 6718 | 70 MB |
pm2 start index.js -i 10 | 4994 | 650 MB |
poolove worker.js | 6519 | 160 MB |
I/O 密集型 + CPU 密集型
在每个请求中都进行一次 fibonacci(30) 的计算,此时单个 nodejs 无法发挥多核的优势,性能最差
方案 | QPS | MEM |
---|---|---|
node index.js | 205 | 70 MB |
pm2 start index.js -i 10 | 1584 | 请求中 720 MB, 空闲 650 MB |
poolove worker.js | 1454 | 请求中 250 MB, 空闲 160MB |
使用
首先编写 worker.js
:
const { poolove } = require("poolove");
const hello = async (body: any) => {
return { ...body };
};
const world = (body: any) => {
return { ...body };
};
poolove.get("/v1/hello", hello);
poolove.post("/v1/world", world);
// 在启动服务之前的钩子
poolove.beforeAll = async () => {
const res = await fetch("http://someting");
console.log(res);
};
module.exports = poolove;
使用 CLI 启动
安装到全局:
npm i -g poolove
启动:
poolove worker.js
默认配置如下:
poolove worker.js --host=127.0.0.1 --port=3800 --timeout=10000
查看服务器状态, 启动后访问: http://localhost:3800/poolove
:
poolove worker.js --info-url='/poolove'
直接使用 Node 命令启动
编写一个 index.js
, 在其中标记 worker.js
的路径
const path = require("path");
const { pooloveServe } = require("poolove/serve.js");
pooloveServe({
filename: path.resolve(__dirname, "./worker.js"),
host: "127.0.0.1",
port: 3800,
infoUrl: "/poolove",
});
然后使用 node 启动 index.js
:
node index.js
通过 PM2 启动
安装到全局:
npm i -g poolove
仅使用 PM2 作为守护进程,仅启动 1 个任务:
pm2 start poolove -- dist/right_worker.js --port=8200 --info-url=/poolove
API
CLI API
参数 | 默认值 |
---|---|
--host | "127.0.0.1" |
--port | 3800 |
--info-url | "" |
--timeout | 10000 |
--min-threads | 0 |
--max-threads | cups.length |
--max-queue | cups.length * 1000 |
执行参数:
interface Options {
host: string;
port: number;
filename: string;
infoUrl?: string;
timeout?: number;
minThreads?: number;
maxThreads?: number;
maxQueue?: number;
}