登录  /  注册
首页 > web前端 > js教程 > 正文

剖析Node.js cluster模块使用详解

php中世界最好的语言
发布: 2018-05-24 09:52:15
原创
1377人浏览过

这次给大家带来剖析Node.js cluster模块使用详解,Node.js cluster模块使用详解的注意事项有哪些,下面就是实战案例,一起来看一下。

cluster模块概览

node实例是单线程作业的。在服务端编程中,通常会创建多个node实例来处理客户端的请求,以此提升系统的吞吐率。对这样多个node实例,我们称之为cluster(集群)。

借助node的cluster模块,开发者可以在几乎不修改原有项目代码的前提下,获得集群服务带来的好处。

集群有以下两种常见的实现方案,而node自带的cluster模块,采用了方案二。

方案一:多个node实例+多个端口

集群内的node实例,各自监听不同的端口,再由反向代理实现请求到多个端口的分发。

  1. 优点:实现简单,各实例相对独立,这对服务稳定性有好处。

  2. 缺点:增加端口占用,进程之间通信比较麻烦。

方案二:主进程向子进程转发请求

集群内,创建一个主进程(master),以及若干个子进程(worker)。由master监听客户端连接请求,并根据特定的策略,转发给worker。

  1. 优点:通常只占用一个端口,通信相对简单,转发策略更灵活。

  2. 缺点:实现相对复杂,对主进程的稳定性要求较高。

入门实例

在cluster模块中,主进程称为master,子进程称为worker。

例子如下,创建与CPU数目相同的服务端实例,来处理客户端请求。注意,它们监听的都是同样的端口。

// server.js
var cluster = require('cluster');
var cpuNums = require('os').cpus().length;
var http = require('http');
if(cluster.isMaster){
 for(var i = 0; i <p style="text-align: left;">创建批处理脚本:./req.sh。</p><pre class="brush:php;toolbar:false">#!/bin/bash
# req.sh
for((i=1;i<p style="text-align: left;">输出如下。可以看到,响应来自不同的进程。</p><blockquote style="text-align: left;"><p style="text-align: left;">response from worker 23735<br>response from worker 23731<br>response from worker 23729<br>response from worker 23730</p></blockquote><p style="text-align: left;"><span style="color: #ff0000"><strong>cluster模块实现原理</strong></span></p><p style="text-align: left;">了解cluster模块,主要搞清楚3个问题:</p><ol class=" list-paddingleft-2">
<li><p style="text-align: left;">master、worker如何通信?</p></li>
<li><p style="text-align: left;">多个server实例,如何实现端口共享?</p></li>
<li><p style="text-align: left;">多个server实例,来自客户端的请求如何分发到多个worker?</p></li>
</ol><p style="text-align: left;">下面会结合示意图进行介绍,源码级别的介绍,可以参考 笔者的github。</p><p style="text-align: left;"><strong>问题1:master、worker如何通信</strong></p><p style="text-align: left;">这个问题比较简单。master进程通过 cluster.fork() 来创建 worker进程。cluster.fork() 内部 是通过 child_process.fork() 来创建子进程。</p><p style="text-align: left;">也就是说:</p><ol class=" list-paddingleft-2">
<li><p style="text-align: left;">master进程、worker进程是父、子进程的关系。</p></li>
<li><p style="text-align: left;">master进程、woker进程可以通过IPC通道进行通信。(重要)</p></li>
</ol><p style="text-align: left;"><strong>问题2:如何实现端口共享</strong></p><p style="text-align: left;">在前面的例子中,多个woker中创建的server监听了同个端口3000。通常来说,多个进程监听同个端口,系统会报错。</p><p style="text-align: left;">为什么我们的例子没问题呢?</p><p style="text-align: left;">秘密在于,net模块中,对 listen() 方法进行了特殊处理。根据当前进程是master进程,还是worker进程:</p><ol class=" list-paddingleft-2">
<li><p style="text-align: left;">master进程:在该端口上正常监听请求。(没做特殊处理)</p></li>
<li><p style="text-align: left;">worker进程:创建server实例。然后通过IPC通道,向master进程<a href="http://www.php.cn/php/php-send-message.html" target="_blank">发送消息</a>,让master进程也创建 server 实例,并在该端口上监听请求。当请求进来时,master进程将请求转发给worker进程的server实例。</p></li>
</ol><p style="text-align: left;">归纳起来,就是:master进程监听特定端口,并将客户请求转发给worker进程。</p><p style="text-align: left;">如下图所示:</p><p style="text-align: left;"><img alt=""    style="max-width:90%"  style="max-width:90%" src="https://img.php.cn/upload/article/000/061/021/392d7540fb965981c01f575d74dd8f15-0.png"></p><p style="text-align: left;"><strong>问题3:如何将请求分发到多个worker</strong></p><p style="text-align: left;">每当worker进程创建server实例来监听请求,都会通过IPC通道,在master上进行注册。当客户端请求到达,master会负责将请求转发给对应的worker。</p><p style="text-align: left;">具体转发给哪个worker?这是由转发策略决定的。可以通过环境变量NODE_CLUSTER_SCHED_POLICY设置,也可以在cluster.setupMaster(options)时传入。</p><p style="text-align: left;">默认的转发策略是轮询(SCHED_RR)。</p><p style="text-align: left;">当有客户请求到达,master会轮询一遍worker列表,找到第一个空闲的worker,然后将该请求转发给该worker。</p><p style="text-align: left;"><strong>master、worker内部通信小技巧</strong></p><p style="text-align: left;">在开发过程中,我们会通过 process.on('message', fn) 来实现进程间通信。</p><p style="text-align: left;">前面提到,master进程、worker进程在server实例的创建过程中,也是通过IPC通道进行通信的。那会不会对我们的开发造成干扰呢?比如,收到一堆其实并不需要关心的消息?</p><p style="text-align: left;">答案肯定是不会?那么是怎么做到的呢?</p><p style="text-align: left;">当发送的消息包含cmd字段,且改字段以NODE_作为前缀,则该消息会被视为内部保留的消息,不会通过message<a href="http://www.php.cn/php/php-tp-incident.html" target="_blank">事件</a>抛出,但可以通过监听'internalMessage'捕获。</p><p style="text-align: left;">以worker进程通知master进程创建server实例为例子。worker伪代码如下:</p><pre class="brush:php;toolbar:false">// woker进程
const message = {
 cmd: 'NODE_CLUSTER',
 act: 'queryServer'
};
process.send(message);
登录后复制

master伪代码如下:

worker.process.on('internalMessage', fn);
登录后复制

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

设计模式的策略模式怎样在前端中使用

如何对微信小程序进行开发

以上就是剖析Node.js cluster模块使用详解的详细内容,更多请关注php中文网其它相关文章!

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
关于CSS思维导图的课件在哪? 课件
凡人来自于2024-04-16 10:10:18
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号