你了解node多进程吗
你了解node多进程吗
面对单进程单线程对多核使用不足的问题,前人的经验是启动多进程即可。理想状态下每个进程各自利用一个CPU,以此实现多核CPU的利用。
所幸,Node提供了 child_process
模块,并且也提供了 child_process.fork()
函数供我们实现进程的复制。
如下所示:
var fork = require('child_process').fork;
var cpus = require('os').cpus();
for (var i = 0; i < cpus.length; i++) {fork('./worker.js');
}
这段代码将会根据当前机器上的CPU数量复制出对应Node进程数。
通过 fork() 复制的进程都是一个独立的进程,这个进程中有着独立而全新的V8实例。它需要至少30毫秒的启动时间和至少10 MB的内存。尽管Node提供了 fork()
供我们复制进程使每个CPU内核都使用上,但是依然要切记 fork()
进程是昂贵的。好在Node通过事件驱动的方式在单线程上解决了大并发的问题,这里启动多个进程只是为了充分将CPU资源利用起来,而不是为了解决并发问题。
在前端浏览器中,JavaScript主线程与UI渲染共用同一个线程。执行JavaScript的时候UI渲染是停滞的,渲染UI时,JavaScript是停滞的,两者互相阻塞。长时间执行JavaScript将会造成UI停顿不响应。
为了解决这个问题,HTML5提出了WebWorker API。WebWorker允许创建工作线程并在后台运行,使得一些阻塞较为严重的计算不影响主线程上的UI渲染。
node进程中怎么通信
通过 fork()
或者其他API,创建子进程之后,为了实现父子进程之间的通信,父进程与子进程之间将会创建IPC通道。通过IPC通道,父子进程之间才能通过 message
和 send()
传递消息。
node多进程一个端口可以被多个进程监听吗
如果让服务都监听到相同的端口,将会有什么样的结果?示例如下所示:
var http = require('http');
http.createServer(function (req, res) {res.writeHead(200, { 'Content-Type': 'text/plain' });res.end('Hello World\n');
}).listen(8888, '127.0.0.1');
第一次启动正常,第二次启动报错,只有一个工作进程能够监听到该端口上,其余的进程在监听的过程中都抛出了 EADDRINUSE 异常,这是端口被占用的情况,新的进程不能继续监听该端口了。这个问题破坏了我们将多个进程监听同一个端口的想法。要解决这个问题,通常的做法是让每个进程监听不同的端口,其中主进程监听主端口,主进程对外接收所有的网络请求,再将这些请求分别代理到不同的端口的进程上。
为了解决上述这样的问题,Node在版本v0.5.9引入了进程间发送句柄的功能。 send()
方法除了能通过IPC发送数据外,还能发送句柄,第二个可选参数就是句柄,如下所示:
child.send(message, [sendHandle])
那什么是句柄?句柄是一种可以用来标识资源的引用,它的内部包含了指向对象的文件描述符。比如句柄可以用来标识一个服务器端socket对象、一个客户端socket对象、一个UDP套接字、一个管道等。
发送句柄意味着什么?在前一个问题中,我们可以去掉代理这种方案,使主进程接收到socket请求后,将这个socket直接发送给工作进程,而不是重新与工作进程之间建立新的socket连接来转发数据。文件描述符浪费的问题可以通过这样的方式轻松解决。来看看我们的示例代码。
主进程代码如下所示:
// parent.js
var cp = require('child_process');
var child1 = cp.fork('child.js');
var child2 = cp.fork('child.js');
var server = require('net').createServer();
server.listen(1337, function () {child1.send('server', server);child2.send('server', server);// 关掉server.close();
});
子进程代码如下所示:
// child.js
var http = require('http');
var server = http.createServer(function (req, res) {res.writeHead(200, { 'Content-Type': 'text/plain' });res.end('handled by child, pid is ' + process.pid + '\n');
});
process.on('message', function (m, tcp) {if (m === 'server') {tcp.on('connection', function (socket) {server.emit('connection', socket);});}
});
这个示例中直接将一个TCP服务器发送给了子进程。多个进程可以监听到相同的端口而不引起 EADDRINUSE 异常。
Cluster模块
Node在v0.8版本时新增的cluster 模块就能解决。在v0.8版本之前,实现多进程架构必须通过 child_process 来实现,要创建单机Node集群,由于有这么多细节需要处理,对普通工程师而言是一件相对较难的工作,于是v0.8时直接引入了 cluster 模块,用以解决多核CPU的利用率问题,同时也提供了较完善的API,用以处理进程的健壮性问题。
对于文章开头提到的创建Node进程集群, cluster实现起来也是很轻松的事情,如下所示:
// cluster.js
var cluster = require('cluster');
cluster.setupMaster({exec: "worker.js"
});
var cpus = require('os').cpus();
for (var i = 0; i < cpus.length; i++) {cluster.fork();
}
事实上 cluster 模块就是 child_process 和 net 模块的组合应用。cluster 启动时,如同我们上文里的代码一样,它会在内部启动TCP服务器,在 cluster.fork()
子进程时,将这个TCP服务器端socket的文件描述符发送给工作进程。
在 cluster 内部隐式创建TCP服务器的方式对使用者来说十分透明,但也正是这种方式使得它无法如直接使用 child_process 那样灵活。
你了解node多进程吗相关推荐
- node 多进程 vs java_node多进程服务器
node提供了四种方法来创建子进程,分别是child_process.exec(),child_process.execFile(), child_process.fork(),child_proce ...
- 《大前端进阶 Node.js》系列 多进程模型底层实现(字节跳动被问)
前言 Coding 应当是一生的事业,而不仅仅是 30 岁的青春饭 本文已收录 Github https://github.com/ponkans/F2E,欢迎 Star,持续更新 字节跳动面试官问: ...
- 宝塔部署node项目_SFF一站式node服务管理平台实践
导语 本文阐述了基于Serverless搭建一站式node服务管理平台过程中,在开发框架.日志.监控.部署等方面遇到的问题及技术方案. 背景 Serverless是一种无服务器架构,它的弹性伸缩,按需 ...
- vue仿今日头条_字节跳动今日头条前端面经(4轮技术面+hr面)
笔者读大三,前端小白一枚,正在准备春招,人生第一次面试,投了头条前端,总共经历了四轮技术面试和一轮hr面,不多说,直接上题 一面 自我介绍,然后问了为什么学习前端 算法:实现36进制转换 简述http ...
- 01 【nodejs简介】
01 [nodejs简介] 1.前言 Node 的重要性已经不言而喻,很多互联网公司都已经有大量的高性能系统运行在 Node 之上.Node 凭借其单线程.异步等举措实现了极高的性能基准.此外,目前最 ...
- 热乎乎的宇宙头条校招前端面经
点击上方"程序员黑叔",选择"置顶或者星标" 你的关注意义重大! 作者:要加油啊 https://juejin.im/post/6844904088337907 ...
- 补充下3月面试题(好未来、腾讯音乐、小药药)
补充一下落下的3月份的面试题,关于春季面经可以看我的上文 .从出师不利.面面具挂,到拿到阿里2个offer 以下是目前还记得的面试题,希望对一些人有用. 好未来 call apply 作用和区别 说 ...
- 业务痛点、个人成长以及未来发展的一些思考
今天我们不讲技术,给大家换换口味 聊聊我个人对发掘业务痛点.个人成长以及未来发展的一些思考 本文索引 发掘业务痛点.个人成长和未来发展的关系 如何发掘业务痛点 业务压力大怎么兼顾个人成长 如何训练自己 ...
- 一些可以参考的文档集合7
之前的文章集合: 一些可以参考文章集合1_xuejianxinokok的博客-CSDN博客 一些可以参考文章集合2_xuejianxinokok的博客-CSDN博客 一些可以参考的文档集合3_xuej ...
最新文章
- 如何挖掘系统的业务价值
- 用户吐槽:Azure DevOps CI 体验太差
- RateLimiter 的底层实现是啥?
- 企业实战之分布式锁方案一步步的演变历程!,Java数据库索引面试题
- nib、xib、storyboard(故事板)
- POJ1988 Cube Stacking
- social science and IP
- 整顿满月,如今现金贷生不如死
- 【转】通用sqlserver分页存储过程
- Mac安装redis与后台启动
- bigdecimal divide四舍五入_BigDecimal 四则运算
- 服务器(Windows镜像)自建git服务器超详细教程
- Linux操作系统安装教程
- 如何运用js制作简单的登录界面(html)
- 2020年9月中国编程语言排行榜
- Baby Sign Language
- 如何处理pagefile.sys占用太多C盘空间
- Command python setup.py egg_info failed with error code 1 in /private/var/folders/14/4hz051qx0wqd3
- java中retry的使用
- world 字体 选取高亮_Word2003选取文字的N种方法
热门文章
- 80% 的学校还在给新生上 C 语言,它们 OUT 了吗?
- 数字蝶变,离不开云原生“苍穹”
- 微信被指监听用户,腾讯回应;谷歌意外推送 Android 11 Beta 更新;Linux 5.7 发布 | 极客头条...
- 2020 年,程序员如何拥抱 5G ?
- 多种方式创建 Entity Framework Core 上下文
- 为什么别人年底购物,同学们年底考证?
- 双十一,不玩盖楼,直接大额降价!
- 山东到底有没有互联网?
- Python 3.8 新功能大揭秘
- 十年无果,Linux 开发者放弃 VMware 诉讼