标题太笼统了。
在分叉工人之前或之后编写我们的服务器逻辑更好吗?
我将在下面举两个例子来阐明这一点。
示例1:
const express = require("express");
const cluster = require('cluster');
const app = express();
app.get("/path", somehandler);
if (cluster.Master)
// forking workers..
else
app.listen(8000);
或示例2:
const cluster = require('cluster');
if (cluster.Master)
// forking workers..
else {
const express = require("express");
const app = express();
app.get("/path", somehandler);
app.listen(8000);
}
有什么区别?
答案 0 :(得分:1)
没有区别。因为当您调用cluster.fork()
时,它将在same entry file上调用child_process.fork
并保留子进程处理程序以进行进程间通信。
阅读在cluster's master模块后面的行中定义的以下方法:167,102,51,52
让我们回到您的代码:
1)在示例#1 中,它分配变量,同时为主流程和子流程创建应用程序实例,然后检查是否为主流程。
2)在示例#2 中,它检查是否存在进程主服务器,如果没有,则分配var,创建应用程序实例并在端口上为子级工作者绑定侦听器。
实际上,它将在clild进程中执行相同的操作:
1)分配变量
2)创建应用实例
3)启动监听器
我自己使用群集的最佳实践包括两个步骤:
步骤1 -在单独的模块中具有自定义群集包装程序,并在应用程序调用中进行包装:
拥有cluster.js
文件:
'use strict';
module.exports = (callable) => {
const
cluster = require('cluster'),
numCPUs = require('os').cpus().length;
const handleDeath = (deadWorker) {
console.log('worker ' + deadWorker.process.pid + ' dead');
const worker = cluster.fork();
console.log('re-spawning worker ' + worker.process.pid);
}
process.on('uncaughtException',
(err) => {
console.error('uncaughtException:', err.message);
console.error(err.stack);
});
cluster.on('exit', handleDeath);
if (numCPUs === 1 || !cluster.isMaster) {
return callable();
}
console.log('Starting', instances, 'instances');
for (let i = 0; i < instances; i++, cluster.fork());
};
为了模块化和可测试性,请像这样app.js
保持简单(有关supertest
的信息):
'use strict';
const express = require("express");
const app = express();
app.get("/path", somehandler);
module.exports = app;
在某个端口提供服务的应用程序必须由其他模块处理,因此server.js
如下所示:
'use strict';
const start = require('./cluster');
start(() => {
const http = require('http');
const app = require('./app');
const listenHost = process.env.HOST || '127.0.0.1';
const listenPort = process.env.PORT || 8080;
const httpServer = http.createServer(app);
httpServer.listen(listenPort, listenHost,
() => console.log('App listening at http://'+listenHost+':'+listenPort));
});
您可以在package.json
部分的scripts
中添加以下行:
"scripts": {
"start": "node server.js",
"watch": "nodemon server.js",
...
}
使用以下命令运行应用程序:
node server.js
,nodemon server.js
或
npm start
,npm run watch
第2步-需要进行容器化时:
保持代码结构,如第1步,并使用docker
集群模块将获取由容器orkestrator提供的cpu资源
另外,您将能够使用docker swarm
,kubernetes
,dc/os
等按需扩展Docker实例。
Dockerfile
:
FROM node:alpine
ENV PORT=8080
EXPOSE $PORT
ADD ./ /app
WORKDIR /app
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
RUN npm i
CMD ["npm", "start"]