javascript - principiantes - En node.js, ¿cómo declarar una variable compartida que puede ser inicializada por el proceso maestro y accedida por los procesos de trabajo?
node js tutorial (5)
En node.js la horquilla no funciona como en C ++. No se copia el estado actual del proceso, se ejecuta un nuevo proceso. Entonces, en este caso las variables no son compartidas. Cada línea de código funciona para cada proceso, pero el proceso maestro tiene un indicador cluster.isMaster establecido en verdadero. Necesita cargar sus datos para cada proceso de trabajo. Tenga cuidado si sus datos son realmente enormes porque cada proceso tendrá su propia copia. Creo que necesitas consultar partes de datos tan pronto como los necesites o esperar si realmente lo necesitas todo en la memoria.
Quiero lo siguiente
- Durante el inicio, el proceso maestro carga una tabla grande desde un archivo y la guarda en una variable compartida. La tabla tiene 9 columnas y 12 millones de filas, con un tamaño de 432 MB.
- Los procesos de trabajo ejecutan el servidor HTTP, aceptando consultas en tiempo real contra la tabla grande.
Aquí está mi código, que obviamente no logra mi objetivo.
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);
}
He intentado guardar la tabla grande en MongoDB para que cada proceso pueda acceder fácilmente a los datos. Pero el tamaño de la tabla es tan grande que a MongoDB le lleva aproximadamente 10 segundos completar mi consulta, incluso con un índice. Esto es demasiado lento y no es aceptable para mi aplicación en tiempo real. También he intentado Redis, que tiene datos en la memoria. Pero Redis es un almacén de valores clave y mis datos son una tabla. También escribí un programa en C ++ para cargar los datos en la memoria, y la consulta tardó menos de 1 segundo, así que quiero emular esto en node.js.
Está buscando una memoria compartida, que node.js simplemente no admite . Debe buscar alternativas, como consultar una base de datos o usar memcached .
Puedes usar Redis.
Redis es un almacén y caché de código clave avanzado de código abierto, con licencia BSD. A menudo se le conoce como un servidor de estructura de datos ya que las claves pueden contener cadenas, hashes, listas, conjuntos, conjuntos ordenados, mapas de bits e hiperloglogs.
redis.io
Si el acceso de solo lectura está bien para su aplicación, pruebe mi propio módulo de memoria compartida . Utiliza mmap
debajo de las cubiertas, por lo que los datos se cargan a medida que se accede y no todos a la vez. La memoria se comparte entre todos los procesos en la máquina. Su uso es muy fácil:
const Shared = require(''mmap-object'')
const shared_object = new Shared.Open(''table_file'')
console.log(shared_object.property)
Le proporciona una interfaz de objeto regular para un almacén de valores o cadenas de valores y claves. Es super rápido en mis aplicaciones.
También hay una versión experimental de lectura-escritura del módulo disponible para pruebas.
Si traduzco su pregunta en pocas palabras, necesita compartir los datos de la entidad MASTER con la entidad WORKER. Se puede hacer muy fácilmente usando eventos:
De maestro a trabajador:
worker.send({json data}); // In Master part
process.on(''message'', yourCallbackFunc(jsonData)); // In Worker part
De Trabajador a Maestro:
process.send({json data}); // In Worker part
worker.on(''message'', yourCallbackFunc(jsonData)); // In Master part
Espero que de esta manera pueda enviar y recibir datos de forma bidireccional. Por favor, márquelo como respuesta si lo encuentra útil para que otros usuarios también puedan encontrar la respuesta. Gracias