当前位置: 首页 > 工具软件 > mod_cluster > 使用案例 >

node集群cluster

仲和韵
2023-12-01

node集群cluster

cludter

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

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

方案一

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

  • 优点:实现简单,各实例相互独立
  • 缺点:增加端口占用,进程之间通信比较麻烦

方案二

集群内,创建一个主进程(master),以及若干个子进程(worker)。由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 < cpuNums; i++){
    cluster.fork();
  }
}else{
  http.createServe(function(req, res){
    res.end(`response from worker ${process.pid}`);
  }).listen(3000);
  console.log(`worker ${process.pid} start`);
}

// 创建批处理脚本:./req.sh
#!/bin/bash
for((i=1;i<=4;i++)); do
    curl http://127.0.0.1:3000   //发出GET请求
    echo ""
done
 
//输出
    response from worker 23735
    response from worker 23731
    response from worker 23729
    response from worker 23730

cluster 模块实现原理

问题一:master、worker 如何通信?

master 进程通过 cluster.fork()来创建 worker 进程,cluster.fork()内部是通过 clild_process.fork()来创建子进程

  • master进程、worker进程是父进程与子进程的关系
  • master进程、worker进程可以通过 IPC 通道进行通信

问题二:如何实现端口共享

const net = require("net");
const server = net.createServer();

net模块中,对listen()方法进行了特殊处理,根据当前进程是master进程还是worker进程:

  • master进程:在该端口上正常监听请求(没做特殊处理)
  • worker进程:创建 serve 实例,然后通过IPC通道,向master进程发送消息,让master进程也创建serve实例,并在该端口上监听请求。当请求进来时,master进程将请求转发给worker进程的serve实例

注意:

主进程master并不会真正去监听端口,端口监听工作始终会交给主进程来完成,主进程在接到子进程worker发来的端口监听的时候,首先会判断是否有相同的服务器,如果有,就直接将子进程worker绑定到对应服务器上,这样就不会出现端口被占用的问题,如果没有对应的服务,就生成一个新的服务。主进程master接受请求时候,就会将请求任务分配给工作进程,如何分配,就需要看具体使用的哪种负载均衡了。

归纳:master进程监听特定端口,并将客户请求转发给worker进程

问题三:如何将请求分发到多个worker

每当worker进程创建server实例来监听请求,都会通过IPC通道,在master上进行注册。当客户端请求到达,master会负责将请求转发给对应的worker

至于转发给那个worker,这个是由转发策略决定的,可以通过环境变量NODE_CLUSTER_SCHED_POLICY设置,也可以在 cluster.setupMaster(options)时传入,默认的转发策略是轮询(SCHED_RR)当有用户请求到达,master会轮询一遍worker列表,找到第一个空闲的worker,然后将请求转发给该worker

 类似资料: