В узлах.js, как объявить общую переменную, которая может быть инициализирована основным процессом и доступна рабочим процессам?

Я хочу, чтобы следующее

  • во время запуска главный процесс загружает большую таблицу из файла и сохраняет ее в общую переменную. Таблица имеет 9 столбцов и 12 миллионов строк размером 432 МБ.
  • рабочие процессы запускают HTTP-сервер, принимая запросы в реальном времени к большой таблице.

вот мой код, который заведомо не достичь своей цели.

var my_shared_var;
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Load a large table from file and save it into my_shared_var,
  // hoping the worker processes can access to this shared variable,
  // so that the worker processes do not need to reload the table from file.
  // The loading typically takes 15 seconds.
  my_shared_var = load('path_to_my_large_table');

  // Fork worker processes
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  // The following line of code actually outputs "undefined".
  // It seems each process has its own copy of my_shared_var.
  console.log(my_shared_var);

  // Then perform query against my_shared_var.
  // The query should be performed by worker processes,
  // otherwise the master process will become bottleneck
  var result = query(my_shared_var);
}

Я попытался сохранить большую таблицу в MongoDB, чтобы каждый процесс может легко получить доступ к данным. Но размер таблицы настолько огромен, что MongoDB занимает около 10 секунд, чтобы завершить мой запрос даже с индексом. Это слишком медленно и неприемлемо для моего приложения в реальном времени. Я также попробовал Redis, который хранит данные в памяти. Но Redis-это хранилище ключевых значений, а мои данные-таблица. Я также написал программу на C++ для загрузки данных в память, и запрос занял менее 1 секунды, поэтому я хочу эмулировать это в node.js.

5 ответов


вы ищете общую память, которая узел.js просто не поддерживает. Вы должны искать альтернативы, такие как запрос к базе данных или через memcached.


Если я переведу Ваш вопрос в несколько слов, вам нужно поделиться данными MASTER entity с WORKER entity. Это можно сделать очень легко, используя события:

от мастера к работнику:

worker.send({json data});    // In Master part

process.on('message', yourCallbackFunc(jsonData));    // In Worker part

от рабочего к мастеру:

process.send({json data});   // In Worker part

worker.on('message', yourCallbackFunc(jsonData));    // In Master part

Я надеюсь, что таким образом вы можете отправлять и принимать данные в обоих направлениях. Пожалуйста, отметьте его как ответ, если вы считаете его полезным, чтобы другие пользователи также могли найти ответ. Спасибо


Если доступ только для чтения подходит для вашего приложения, попробуйте мой собственный модуль общей памяти. Он использует mmap под обложками, поэтому данные загружаются по мере доступа, а не все сразу. Память распределяется между всеми процессами на машине. Используя его очень легко:

const Shared = require('mmap-object')

const shared_object = new Shared.Open('table_file')

console.log(shared_object.property)

это дает вам обычный интерфейс объекта для хранилища строк или чисел. Это очень быстро в моих приложениях.

есть экспериментальное чтение-запись версия модуля доступна для тестирования.


в узел.JS fork работает не так, как в C++. Это не копировать текущее состояние процесса, это запустить новый процесс. Таким образом, в этом случае переменные не передаются. Каждая строка кода работает для каждого процесса, но главный процесс имеет кластер.isMaster флаг установлен в true. Вам необходимо загрузить данные для каждого рабочего процесса. Будьте осторожны, если ваши данные действительно огромный, потому что каждый процесс будет иметь свою собственную копию. Я думаю, вам нужно запросить части данных, как только они вам понадобятся, или подождать, если вам действительно нужно все это память.


вы можете использовать Redis.

Redis - это открытый исходный код, лицензированный BSD, расширенный кэш значений ключей и магазин. Его часто называют сервером структуры данных, поскольку ключи могут содержать строки, хэши, списки, наборы, отсортированные наборы, растровые изображения и гиперлоги.

redis.Ио