NodeJs: 使用cluster创建nodejs单机多核集群(多进程)
来源:互联网 发布:linux 内核书籍 编辑:程序博客网 时间:2024/05/16 10:19
前言:
nodejs提供了cluster集群(支持端口共享的多进程),cluster基于child_process,process二次封装,方便我们使用该功能实现单机nodejs的web集群。
1、cluster的处理机制
都知道单线程的nodejs遇到cpu密集型操作会很容易出现CPU满载,服务阻塞的问题;通过类似nginx的master-worker多进程负载处理方式进一步压榨硬件性能,提升nodejs单机服务处理性能。
m a s t e r(主进程,分发请求)
| | | |
worker worker worker worker(子进程,处理请求)
2、官方cluster实现
nodejs官方文档中cluster的实现demo:
const cluster = require('cluster');const http = require('http');const numCPUs = require('os').cpus().length;if (cluster.isMaster) { for (var i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); });} else { http.createServer((req, res) => { res.writeHead(200); res.end('hello world\n'); }).listen(8000);}
3、实现自己的单机nodejs集群,实现多进程端口共享
3.1、代码实现
-
- var startClusterSever = function(port, numCPUs) {
- if (cluster.isMaster) {
- for (var i = 0; i < numCPUs; i++) {
- const work = cluster.fork();
- console.log(work.process.pid);
- workers[i] = work;
- }
- cluster.on('exit', (worker, code, signal) => {
- console.log(`worker ${worker.process.pid} died`);
- });
- } else {
- console.log(cluster.worker.id);
- http.createServer((req, res) => {
- console.log("子进程:" + cluster.worker.id + "正在处理请求...");
- routeHandler(req, res);
- }).listen(port);
-
- }
- }
3.2、基于eguidRoute路由实现
注:在上一章的eguidRoute基础上增加开启单机集群功能
使用:
eguid.start(8081, 8);//监听8081端口,多线程数量8
- const http = require('http');
- const url = require('url');
- const path = require('path');
- const fs = require('fs');
- const cluster = require('cluster');
-
- var routeArr = {};
-
- var workers = {};
-
- var clusterNum;
-
- var getPathName = function(reqUrl) {
- var urlParse = getUrlParse(reqUrl);
- return urlParse.pathname;
- };
-
- var getUrlParse = function(reqUrl) {
- return url.parse(reqUrl);
- };
-
- var isFunc = function(pathName) {
- return typeof routeArr[pathName] === 'function';
- };
-
- var resStatic = function(req, res, pathName) {
- fs.readFile(pathName.substr(1), function(err, data) {
- err ? endErrorReq(res, 501) : endStaticReq(res, pathName, data);
- res.end();
- });
- };
-
- var endStaticReq = function(res, pathName, data) {
- var suffix = path.extname(pathName);
- res.writeHead(200, { 'Content-Type': suffix === ".css" ? 'text/css' : 'text/html;' + 'charset=utf-8' });
- res.write(data);
- };
-
- var endErrorReq = function(res, err) {
- res.writeHead(err);
- res.end();
- };
-
- var routeHandler = function(req, res) {
- var pathName = getPathName(req.url);
- isFunc(pathName) ? routeArr[pathName](req, res, pathName) : resStatic(req, res, pathName);
- console.log("处理了一个请求:" + pathName);
- };
-
-
-
-
-
- var addDynamicRoute = function(reqUrl, service) {
- console.log("添加的服务名:" + reqUrl);
- routeArr[reqUrl] = service;
- };
-
- var startServer = function(port, num) {
- clusterNum = num;
- if (num) {
- startClusterSever(port, num);
- } else {
-
- http.createServer(function(req, res) {
- routeHandler(req, res);
- }).listen(port);
-
- console.log('Server running at http://127.0.0.1:' + port);
- }
- };
-
- var setIndex = function(newUrl, oldUrl) {
- addDynamicRoute(newUrl, function(req, res) {
- resStatic(req, res, oldUrl);
- });
- };
-
- var setresStaticFunc = function(staticHandlerService) {
- resStatic = staticHandlerService;
- };
-
-
- var startClusterSever = function(port, numCPUs) {
- if (cluster.isMaster) {
- for (var i = 0; i < numCPUs; i++) {
- const work = cluster.fork();
- console.log(work.process.pid);
- workers[i] = work;
- }
- cluster.on('exit', (worker, code, signal) => {
- console.log(`worker ${worker.process.pid} died`);
- });
- } else {
- console.log(cluster.worker.id);
- http.createServer((req, res) => {
- console.log("子进程:" + cluster.worker.id + "正在处理请求...");
- routeHandler(req, res);
- }).listen(port);
-
- }
- }
- exports.route = routeHandler;
- exports.add = addDynamicRoute;
- exports.start = startServer;
- exports.index = setIndex;
- exports.modStatic = setresStaticFunc;
-
-
-
-
-
-
-
-
-
-
-