弱弱地问一下,cluster 和 child_process 的使用场景
发布于 8 年前 作者 riskers 6520 次预览 最后一次回复是 6 年前 来自 问答
我对服务端开发的认知还处在 curd 的阶段,所以这些进程之类的并没有使用过。最近又开始进入 Node 的世界,所以产生了一些疑问:
- 大家说说在什么项目里,或者自己在什么场景下用到过进程,cluster 和 child process 的使用场景有那些,并且说说为什么
- 以及在大家熟悉的其他的后端语言中,是否都存在调用进程的场景
本人 3 年前端经验,就像上面说的,对服务端开发的认知还处在 curd 的阶段,所以希望大家不吝赐教。谢谢
cluster 和 child process 的概念也都看了,就是压榨机器,提升性能。不过这些是不是加机器也能做到,如果是一个集群的情况下呢?
11 回复
https://nodejs.org/api/cluster.html#cluster_how_it_works
@atian25 谢谢大神回复
现在用到 puppeteer 来做测试平台,场景如下: 我要每分钟查一次表
report_list中 status=1 的字段来得到数据,根据得到的一串数据(比如10条),执行一次计算(跑一遍puppeteer,然后截图,并且上传到 CDN,这个过程要1分钟左右,10条就是10分钟),然后把得到的 CDN地址存入另一张表,同时把report_list中这条记录status置为0.我的思路卡在:在 schedule 中每分钟查库,然后执行命令,但是这个命令(可能会10分钟),这样就会每分钟开启一个10分钟的任务,这样对么?不知道这种情况应该怎么设计,是要运用到 cluster 么
@yszou 请看看我上面补充的描述,这种场景下我该怎么设计
cluster底层就是child_process@riskers
是我做的话,我不会自己去做 fork 的。
我只写一个程序,这个程序做的事,首先,这个程序自带 timer ( nodejs 已经有了),然后,每 10 秒查一次库吧,不需要 1 分钟,因为查询成本不高,这个自己控制(因为自带 timer ,所以只要把异常处理好,这个程序可以一直运行的。有异常挂掉也没什么,外面还有专门的进程管理工具兜底)。每查一次库,只取一条 report 记录,并把它的 status 先改成 2 ,表示“正在处理之类”,这个 update 操作注意加锁,别让其它程序也查到同样的记录了(关系数据库基本功能)。同时可以在记录中加个属性,表示“开始处理的时间”,还可以加个属性,表示“处理程序的进程ID”。
然后,这个程序开始做需要做的事,比如需要 1 分钟才能完成。正常结束之后,再 update 把 status 改成 0 。
接着,找一个专门的进程管理工具,nodejs 的 PM2 (没用过,看介绍应该做进程管理用的), Python 的 supervisor 等,根据机器的配置, CPU 核数,在不同机器上启动 N 个这个程序就好了。剩下的事进程管理工具会解决,记得做成随机器启动。
再完善一点,可以再作一个专门的额外监控程序,每 1 分钟检查一下 report 记录的状态,通过“开始处理时间”判断一下,如果这个时间超过了 2 分钟,明显不正常了,那么通过 supervisor (我不知道 PM2 有没有) 的 RPC 接口,把对应的进程干掉,重启,对应 status 改成 1 。(这个额外的程序也可以加到进程管理工具的启动当中,即使没台机器都重复跑了一个这样的东西,也没有关系)
简简单单的,这个小的程序你部署到几十台机器都没有问题。(当然,如何部署分发,是另一个话题了)
你们说的已经很全了。我再补充个实践例子,比如webpack打包的时候,文件越多越慢,其实也可以利用这个机制来实现多进程打包的。ykit就是这样做的。
@yszou 谢谢,因为是基于 eggjs 搞得,所以你说的这些操作我理解是不是能放在 agent.js 里去做。https://eggjs.org/zh-cn/core/cluster-and-ipc.html
@riskers
怎么写看你自己了吧。 跟 web 没关系,跟 eggjs 也没有直接关系的。你写一个 worker.js 放到项目的任何一个地方就可以了,反正运行只是
node worker.js就好了啊。@riskers 三楼的就等于需要跑10个子进程,直接child_process.exec不好吗。。
楼主的问题怎么解决的,多线程的问题先不说,
如果每分钟开始一个新任务,任务周期都是10分钟,产生速率比消耗速率大,这样任务数量会越来越多吧,资源会被撑爆了对吗?