什么是Node js集群最佳实践?

时间:2018-08-19 08:07:23

标签: javascript node.js server

标题太笼统了。

在分叉工人之前或之后编写我们的服务器逻辑更好吗?

我将在下面举两个例子来阐明这一点。

示例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);
}

有什么区别?

1 个答案:

答案 0 :(得分:1)

没有区别。因为当您调用cluster.fork()时,它将在same entry file上调用child_process.fork并保留子进程处理程序以进行进程间通信。

阅读在cluster's master模块后面的行中定义的以下方法:1671025152


让我们回到您的代码:

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.jsnodemon server.js

npm startnpm run watch



第2步-需要进行容器化时:

保持代码结构,如第1步,并使用docker

集群模块将获取由容器orkestrator提供的cpu资源

另外,您将能够使用docker swarmkubernetesdc/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"]