Кластер NodeJS на AWS Lambda

Можно ли использовать модуль кластера в лямбда-функциях? Я пробовал это:

'use strict';
var cluster = require('cluster');  
var http    = require('http');  
var os      = require('os');

var numCPUs = os.cpus().length;
console.log('Number of Cores : ', numCPUs);

exports.test = (event, context, callback) => {
    if (cluster.isMaster) {
        for (var i = 0; i < numCPUs; ++i) {
            cluster.fork();
        }
    } else {
        console.log('child process ');
    }
}

количество ядер всегда равно 2, но я никогда не вижу журнал дочернего процесса.

Обновление для примера комментариев:

Я попытался реализовать шаблон сообщения, но я все еще не получаю сообщение, отправленное дочерними элементами. Цикл for корректно пересекает работу кластера, но никогда не находит сообщение.

'use strict';
var cluster = require('cluster');  
var http    = require('http');  
var os      = require('os');

var numCPUs = os.cpus().length;
console.log('Number of Cores : ', numCPUs);

exports.test = (event, context, callback) => {
    if (cluster.isMaster) {
        for (var i = 0; i < numCPUs; ++i) {
            cluster.fork();
        }
        for (const id in cluster.workers) {
            cluster.workers[id].on('message', messageHandler);
        }
    } else {
        process.send('running');
    }
};

function messageHandler(msg) {
    console.log(msg);
}

Ответ 1

Проблема заключается в том, что нет ничего, чтобы вызвать функцию exports.test для каждого из дочерних процессов. cluster.fork() вызывает новый экземпляр файла с разными параметрами, который начинается с начала, в отличие от системного вызова fork() в C, который клонирует текущий процесс и продолжается из той же строки как в родительском, так и в дочернем процессах.

Для родительского процесса AWS lambda вызовет эту функцию, но дочерний процесс просто определяет функцию, а затем ждет.

Я бы перевернул вашу логику, чтобы проверка cluster.isMaster происходила вокруг всего остального; Я проверил следующее локально:

'use strict';
let cluster = require('cluster')
let http = require('http')
let os = require('os')

let numCPUs = os.cpus().length

if (cluster.isMaster) {
  console.log('Number of Cores : ', numCPUs);
  exports.test = (event, context, callback) => {
    for (let i = 0; i < numCPUs; ++i) {
      cluster.fork();
    }
    for (const id in cluster.workers) {
      cluster.workers[id].on('message', messageHandler);
    }
  }
} else {
  process.send('running');
}

function messageHandler(msg) {
  console.log(msg);
}

// The following used for local test

exports.test && exports.test();

Ответ 2

Ваш код выглядит правильно, за исключением того, что вы делаете предположение, что вызов console.log() от рабочего отображается на консоли для вашего основного процесса. Это не всегда так, поскольку вызовы не распространяются на дерево процессов.

После ваших вызовов на fork() отправьте этот фрагмент, чтобы получить сообщение от дочернего процесса:

for (var id in cluster.workers) {
  cluster.workers[id].on('message',function () {
    console.log('got message from ' + id + ': ' + msg);
  });
}

Затем в вашем втором случае вашего if/else (где хранятся запросы рабочего процесса) добавьте это сообщение в мастер:

process.send('running');

Вы также можете отправлять объекты (предпочтительнее) через process.send(), я просто использовал String в качестве примера. Более подробная информация о официальных документах: Cluster - как это работает