Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >NodeJS多核处理模cluster解读

NodeJS多核处理模cluster解读

作者头像
用户2936342
发布于 2018-08-27 06:53:43
发布于 2018-08-27 06:53:43
85920
代码可运行
举报
文章被收录于专栏:nummynummy
运行总次数:0
代码可运行

参考 http://blog.fens.me/nodejs-core-cluster/

大家都知道nodejs是一个单进程单线程的服务器引擎,不管有多么的强大硬件,只能利用到单个CPU进行计算。所以,有人开发了第三方的cluster,让node可以利用多核CPU实现并行。

1. cluster介绍

cluster是一个nodejs内置的模块,用于nodejs多核处理。cluster模块,可以帮助我们简化多进程并行化程序的开发难度,轻松构建一个用于负载均衡的集群。

2. cluster的简单使用

在win的环境中,我们通过cluster启动多核的node提供web服务。 新建文件:app.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    console.log("master start...");

    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('listening',function(worker,address){
        console.log('listening: worker ' + worker.process.pid +', Address: '+address.address+":"+address.port);
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
    }).listen(0);
}

在控制台启动node程序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
λ node server.js
master start...
listening: worker 12976, Address: null:50047
listening: worker 14716, Address: null:50047
listening: worker 14184, Address: null:50047
listening: worker 14820, Address: null:50047

master是总控节点,worker是运行节点。然后根据CPU的数量,启动worker。我本地是双核双通道的CPU,所以被检测为4核,启动了4个worker。

3. cluster的工作原理

每个worker进程通过使用child_process.fork()函数,基于IPC(Inter-Process Communication,进程间通信),实现与master进程间通信。

当worker使用server.listen(...)函数时 ,将参数序列传递给master进程。如果master进程已经匹配workers,会将传递句柄给工人。如果master没有匹配好worker,那么会创建一个worker,再传递并句柄传递给worker。

在边界条件,有3个有趣的行为: 注:下面server.listen(),是对底层“http.Server-->net.Server”类的调用。

  1. server.listen({fd: 7}):在master和worker通信过程,通过传递文件,master会监听“文件描述为7”,而不是传递“文件描述为7”的引用。
  2. server.listen(handle):master和worker通信过程,通过handle函数进行通信,而不用进程联系
  3. server.listen(0):在master和worker通信过程,集群中的worker会打开一个随机端口共用,通过socket通信,像上例中的57132 当多个进程都在 accept() 同样的资源的时候,操作系统的负载均衡非常高效。Node.js没有路由逻辑,worker之间没有共享状态。所以,程序要设计得简单一些,比如基于内存的session。

因为workers都是独力运行的,根据程序的需要,它们可以被独立删除或者重启,worker并不相互影响。只要还有workers存活,则master将继续接收连接。Node不会自动维护workers的数目。我们可以建立自己的连接池。

4. cluster的API

cluster对象 cluster的各种属性和函数 cluster.setttings:配置集群参数对象 cluster.isMaster:判断是不是master节点 cluster.isWorker:判断是不是worker节点 Event: 'fork': 监听创建worker进程事件 Event: 'online': 监听worker创建成功事件 Event: 'listening': 监听worker向master状态事件 Event: 'disconnect': 监听worker断线事件 Event: 'exit': 监听worker退出事件 Event: 'setup': 监听setupMaster事件 cluster.setupMaster([settings]): 设置集群参数 cluster.fork([env]): 创建worker进程 cluster.disconnect([callback]): 关闭worket进程 cluster.worker: 获得当前的worker对象 cluster.workers: 获得集群中所有存活的worker对象

worker对象 worker的各种属性和函数:可以通过cluster.workers, cluster.worket获得。 worker.id: 进程ID号 worker.process: ChildProcess对象 worker.suicide: 在disconnect()后,判断worker是否自杀 worker.send(message, [sendHandle]): master给worker发送消息。注:worker给发master发送消息要用process.send(message) worker.kill([signal='SIGTERM']): 杀死指定的worker,别名destory() worker.disconnect(): 断开worker连接,让worker自杀 Event: 'message': 监听master和worker的message事件 Event: 'online': 监听指定的worker创建成功事件 Event: 'listening': 监听master向worker状态事件 Event: 'disconnect': 监听worker断线事件 Event: 'exit': 监听worker退出事件

5. master和worker的通信

实现cluster的API,让master和worker相互通信。 新建文件: cluster.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    console.log('[master] ' + "start master...");

    for (var i = 0; i < numCPUs; i++) {
        var wk = cluster.fork();
        wk.send('[master] ' + 'hi worker' + wk.id);
    }

    cluster.on('fork', function (worker) {
        console.log('[master] ' + 'fork: worker' + worker.id);
    });

    cluster.on('online', function (worker) {
        console.log('[master] ' + 'online: worker' + worker.id);
    });

    cluster.on('listening', function (worker, address) {
        console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
    });

    cluster.on('disconnect', function (worker) {
        console.log('[master] ' + 'disconnect: worker' + worker.id);
    });

    cluster.on('exit', function (worker, code, signal) {
        console.log('[master] ' + 'exit worker' + worker.id + ' died');
    });

    function eachWorker(callback) {
        for (var id in cluster.workers) {
            callback(cluster.workers[id]);
        }
    }

    setTimeout(function () {
        eachWorker(function (worker) {
            worker.send('[master] ' + 'send message to worker' + worker.id);
        });
    }, 3000);

    Object.keys(cluster.workers).forEach(function(id) {
        cluster.workers[id].on('message', function(msg){
            console.log('[master] ' + 'message ' + msg);
        });
    });

} else if (cluster.isWorker) {
    console.log('[worker] ' + "start worker ..." + cluster.worker.id);

    process.on('message', function(msg) {
        console.log('[worker] '+msg);
        process.send('[worker] worker'+cluster.worker.id+' received!');
    });

    http.createServer(function (req, res) {
            res.writeHead(200, {"content-type": "text/html"});
            res.end('worker'+cluster.worker.id+',PID:'+process.pid);
    }).listen(3000);

}

输出信息如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[master] start master...
[worker] start worker ...1
[worker] [master] hi worker1
[worker] start worker ...2
[worker] [master] hi worker2
[master] fork: worker1
[master] fork: worker2
[master] fork: worker3
[master] fork: worker4
[master] online: worker1
[master] online: worker2
[master] message [worker] worker1 received!
[master] message [worker] worker2 received!
[master] listening: worker1,pid:6068, Address:0.0.0.0:3000
[master] listening: worker2,pid:1408, Address:0.0.0.0:3000
[master] online: worker3
[worker] start worker ...3
[worker] [master] hi worker3
[master] message [worker] worker3 received!
[master] listening: worker3,pid:3428, Address:0.0.0.0:3000
[master] online: worker4
[worker] start worker ...4
[worker] [master] hi worker4
[master] message [worker] worker4 received!
[master] listening: worker4,pid:6872, Address:0.0.0.0:3000
[worker] [master] send message to worker1
[worker] [master] send message to worker2
[worker] [master] send message to worker3
[worker] [master] send message to worker4
[master] message [worker] worker1 received!
[master] message [worker] worker2 received!
[master] message [worker] worker3 received!
[master] message [worker] worker4 received!

6. 用cluster实现负载均衡(Load Balance) -- win7失败

新建文件: server.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    console.log('[master] ' + "start master...");

    for (var i = 0; i < numCPUs; i++) {
         cluster.fork();
    }

    cluster.on('listening', function (worker, address) {
        console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
    });

} else if (cluster.isWorker) {
    console.log('[worker] ' + "start worker ..." + cluster.worker.id);
    http.createServer(function (req, res) {
        console.log('worker'+cluster.worker.id);
        res.end('worker'+cluster.worker.id+',PID:'+process.pid);
    }).listen(3000);
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.04.07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
2 条评论
热度
最新
你好,我这边使用webpack5+react18搭建了一个项目,目前想接入ts,按照目前的搭建方法,接入ts需要怎么做呢?
你好,我这边使用webpack5+react18搭建了一个项目,目前想接入ts,按照目前的搭建方法,接入ts需要怎么做呢?
回复回复点赞举报
从run build就走不下去了 - -!```[webpack-cli] Failed to load '/Users/yoocoo/Documents/fe/demo/build/webpack.config.js' config SyntaxError: Invalid or unexpected token
从run build就走不下去了 - -!```[webpack-cli] Failed to load '/Users/yoocoo/Documents/fe/demo/build/webpack.config.js' config SyntaxError: Invalid or unexpected token
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
一文彻底读懂webpack常用配置
const TerserPlugin = require('terser-webpack-plugin');
gogo2027
2022/10/18
4510
webpack 入门教程
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
老马
2018/08/20
4K0
webpack 入门教程
webpack4实用配置指南-上手篇
算起来已经有3到4个项目的webpack构建打包经历。然而每次搭建起来还是有新手既视感,比较捉急。工具用法的东西,好记性不如烂笔头,有必要系统梳理下webpack的配置常用配置以及构建优化。
elson
2018/06/19
4.8K0
webpack 从入门到放弃
Webpack + ES6 已经成为目前最流行的前端解决方案,本文是 Webpack2 学习教程。
李振
2021/11/26
6070
手把手教你全家桶之React(三)--完结篇
前言 本篇主要是讲一些全家桶的优化与完善,基础功能上一篇已经讲得差不多了。直接开始: Source Maps 当javaScript抛出异常时,我们会很想知道它发生在哪个文件的哪一行。但是webpack 总是将文件输出为一个或多个bundle,我们对错误的追踪很不方便。Source maps试图解决这一个问题,我们只需要改变一下配置项即可。 在webpack.dev.config.js中加入: devtool:"inline-source-map" css编译 这里以less-loader为例,先安装 l
用户2145235
2018/06/26
1.1K0
​(非软文)Webpack从入门到实战搭建Vue脚手架(一万字总结)
安装依赖包 (-D 将依赖记录成开发依赖, 只是开发中需要用的依赖, 实际上线不需要的)
Vam的金豆之路
2021/12/01
1.3K0
webpack 基础知识整理
webpack是一个 模块打包工具,支持所有的打包语法,比如 ES Module、CommonJS、CMD、AMD。初期的webpack是用来模块打包js的,发展到现在,已经可以打包很多种文件类型,比如 css、img 。
神葳
2021/01/22
1.4K0
webpack构建自定义react应用
首先我们要确定,react并不是在webpack中像插件一样安装就可以直接使用,我们需要支持jsx以及一些es6的一些比较新的语法,在creat-react-app这个脚手架中已经帮我们高度封装了react项目的一些配置,甚至你是看不到很多的配置,比如@babel/preset-react转换jsx等。所以我们需要知道一个react项目需要哪些插件的前提条件,本文主要参考从头开始打造工具链[1]
Maic
2022/07/28
5390
webpack构建自定义react应用
webpack4.x常用配置
yarn init -y yarn add webpack webpack-cli -D
FinGet
2020/01/13
2K0
webpack4.x常用配置
用 webpack 4.0 撸单页/多页脚手架 (jquery, react, vue, typescript)
首先来简单介绍一下webpack:现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个会映射项目所需的每个模块 的依赖图(dependency graph),并生成一个或多个 bundle。webpack4.0出现之后,我们可以不用再引入一个配置文件来打包项目,并且它仍然有着很高的可配置性,可以很好满足我们的需求。 在开始正文之前,首先先来看看我们要实现的成果:
徐小夕
2019/08/08
2.4K0
用 webpack 4.0 撸单页/多页脚手架 (jquery, react, vue, typescript)
从零开始搭建Vue工程
dist目录存放编译后的资源 src存放源码文件 运行命令 npm init -y
切图仔
2022/09/08
8580
从零开始搭建Vue工程
大作!webpack详细配置
注意:在一个模块中,只允许使用export default向外默认暴露一次成员,不能写多个export default,否则会报错
小丞同学
2021/08/16
1.7K0
webpack 4 的 30 个步骤打造优化到极致的 react 开发环境
将 react 和 webpack4 进行结合,集 webpack 的优势于一身,从 0 开始构建一个强大的 react 开发环境。
夜尽天明
2019/06/18
2.4K0
webpack配置完全指南
首先webpack是一个静态模块打包器,所谓的静态模块,包括脚本、样式表和图片等等;webpack打包时首先遍历所有的静态资源,根据资源的引用,构建出一个依赖关系图,然后再将模块划分,打包出一个或多个bundle。再次白piao一下官网的图,生动的描述了这个过程:
gogo2027
2022/10/03
1.3K0
从零搭建一个 webpack 脚手架工具(一)
webpack 是一个现代 JavaScript 应用程序的静态模块打包器,已经成为前端开发不可获取的工具。特别是在开发大型项目时,项目太大,文件过多导致难以维护,或者是优化网络请求时,webpack 都是不可获取的利器。但是 webpack 配置并没有那么容易,webpack 配置项繁多,繁多的背后是配置的灵活性。许多的框架都是由 webpack 搭建而成,因此学会使用 webpack 可以让自己更好的理解脚手架搭建过程,甚至自己写一个灵活高效的脚手架工具。
多云转晴
2019/12/05
1.7K0
【Webpack】320- Webpack4 入门手册(共 18 章)(下)
最近和部门老大,一起在研究团队【EFT - 前端新手村】的建设,目的在于:帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发并且达到公司业务开发水平。
pingan8787
2019/08/20
2.4K0
【Webpack】320- Webpack4 入门手册(共 18 章)(下)
webpack超详细教程!入门一篇就够了
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
beifengtz
2019/08/26
9.9K0
webpack超详细教程!入门一篇就够了
入门webpack的最佳实践(基于webpack4.X 5.X)--基础篇
来到这家公司之后,一直在使用webpack,也写了不少笔记,但是都比较零散,现在决定整理一下webpack相关的知识点,由浅入深,方便自己后续查漏补缺,后续会一直更新。
Jou
2022/08/18
6610
入门webpack的最佳实践(基于webpack4.X 5.X)--基础篇
webpack4配置入门和进阶
webpack作为一个模块打包器,主要用于前端工程中的依赖梳理和模块打包,将我们开发的具有高可读性和可维护性的代码文件打包成浏览器可以识别并正常运行的压缩代码,主要包括样式文件处理成css,各种新式的JavaScript转换成浏览器认识的写法等,也是前端工程师进阶的不二法门,本文借鉴了部分vue-cli对webpack的配置思路,还有一些网上比较好的解决方案,在此对这些作者一并表示感谢。 webpack.config.js配置项简介 Entry:入口文件配置,Webpack 执行构建的第一步将从 Entry
卡少
2018/05/16
3.5K0
【Cute-Webpack】Webpack4 入门手册(共 18 章)
最近和部门老大,一起在研究团队【EFT - 前端新手村】的建设,目的在于:帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发并且达到公司业务开发水平。
pingan8787
2019/08/15
2.4K1
相关推荐
一文彻底读懂webpack常用配置
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验