如何使用Mochatesting集群快速应用程序?

以下是我的集群Express应用程序的简化版本:

/index.js

module.exports = process.env.CODE_COV ? require('./lib-cov/app') : require('./lib/app'); 

/lib/app.js

 var cluster = require('cluster'), express = require('express'), app = module.exports = express.createServer(); if (cluster.isMaster) { // Considering I have 4 cores. for (var i = 0; i < 4; ++i) { cluster.fork(); } } else { // do app configurations, then... // Don't listen to this port if the app is required from a test script. if (!module.parent.parent) { app.listen(8080); } } 

/test/test1.js

 var app = require('../'); app.listen(7777); // send requests to app, then assert the response. 

问题:

  1. var app = require('../'); 将无法在此群集环境中工作。 应该返回哪个工作应用程序? 它应该返回群集对象,而不是一个Express应用程序?
  2. 现在,显然在testing脚本中设置端口将不起作用。 你将如何设置一个testing脚本内的端口到应用程序集群?
  3. 你将如何发送请求到这个应用程序集群?

我能想到的唯一解决scheme是有条件地closures集群function,并且只运行一个应用程序( if (module.parent.parent) ... )请求应用程序。

任何其他方式来与摩卡testing集群快递应用程序?

我发布这个问题已经很长时间了。 由于没有人回答,所以我会自己回答这个问题。

我保留/index.js,因为它是:

 module.exports = process.env.CODE_COV ? require('./lib-cov/app') : require('./lib/app'); 

在启动集群的/lib/app.js中,我有以下代码。 简而言之,我只在非testing环境中启动群集。 在testing环境中,集群未启动,但只有一个应用/工作者本身按照cluster.isMaster && !module.parent.parent条件中的定义启动。

 var cluster = require('cluster'), express = require('express'), app = module.exports = express.createServer(); if (cluster.isMaster && !module.parent.parent) { // Considering I have 4 cores. for (var i = 0; i < 4; ++i) { cluster.fork(); } } else { // do app configurations, then... // Don't listen to this port if the app is required from a test script. if (!module.parent.parent) { app.listen(8080); } } 

在上面的情况下,只有在应用程序没有被testing脚本启动的情况下, !module.parent.parent才会被评估为真实的对象。

  1. module是当前的/lib/app.js脚本。
  2. module.parent是它的父级/index.js脚本。
  3. 如果应用程序直接通过node index.js启动,则module.parent.parentundefined的。
  4. module.parent.parent是如果应用程序是通过其中一个脚本启动的testing脚本。

因此,我可以安全地启动我可以设置自定义端口的脚本。

/test/test1.js

 var app = require('../'); app.listen(7777); // send requests to app, then assert the response. 

同时,如果我需要真正运行应用程序,即不用于testing,那么我运行node index.js ,它将启动应用程序集群。

我有一个更简单的方法来做到这一点

  if (process.env.NODE_ENV !== 'test') { if (cluster.isMaster) { var numCPUs = require('os').cpus().length; console.log('total cpu cores on this host: ', numCPUs); for (var i = 0; i < numCPUs; i++) { console.log('forking worker...'); cluster.fork(); } cluster.on('online', function(worker) { console.log('Worker ' + worker.process.pid + ' is online.'); }); cluster.on('exit', function(worker, code, signal) { console.log('worker ' + worker.process.pid + ' died.'); }); } else { console.log('Im a worker'); // application code setupServer() } } else { // when running tests setupServer(); } 

只要确保在运行test时将env设置为testNODE_ENV=test grunt test

我喜欢你的解决scheme,因为它很简单,但是,在一个像MVC框架的节点环境中,你最终可能会链接module.parent最多11次(严重)。

我认为一个更好的方法是简单地检查哪个脚本节点开始处理。 节点的命令行参数在process.argv处可用。 这个数组中的第一个项目是'node',可执行文件和第二个参数是节点开始执行的文件的path。 这将是index.js在你的情况。

所以,而不是检查

  module.parent.parent ^ ^ (app.js) | (index.js) 

你可以做这样的事情

 var starter = process.argv[1].split(path.sep).pop(); 

哪里starter将是indexindex.js取决于你开始你的服务器。 node index.js vs node index

然后检查看起来像:

 if (cluster.isMaster && starter === 'index.js') { cluster.fork(); } 

在我的环境中工作 – 我希望这有助于!