Dans node.js, comment déclarer une variable partagée pouvant être initialisée par le processus maître et accessible par les processus de travail?

Je veux le suivant

  • Lors du démarrage, le processus maître charge une grande table à partir d’un fichier et l’enregistre dans une variable partagée. Le tableau comporte 9 colonnes et 12 millions de lignes, dont la taille est de 432 Mo.
  • Les processus de travail exécutent le serveur HTTP, acceptant les requêtes en temps réel sur la grande table.

Voici mon code, qui n’atteint évidemment pas mon objective.

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

J’ai essayé d’enregistrer la grande table dans MongoDB afin que chaque processus puisse facilement accéder aux données. Mais la taille de la table est si énorme qu’il faut environ 10 secondes à MongoDB pour compléter ma requête, même avec un index. C’est trop lent et pas acceptable pour mon application en temps réel. J’ai aussi essayé Redis, qui contient des données en mémoire. Mais Redis est un magasin de valeurs-clés et mes données sont une table. J’ai également écrit un programme C ++ pour charger les données en mémoire et la requête a pris moins d’une seconde. Je souhaite donc émuler cela dans node.js.

    Vous recherchez une mémoire partagée, que node.js ne prend tout simplement pas en charge . Vous devez rechercher des alternatives, telles que l’ interrogation d’une firebase database ou l’utilisation de memcached .

    Si je traduis votre question en quelques mots, vous devez partager les données de l’entité MASTER avec l’entité WORKER. Cela peut être fait très facilement en utilisant des événements:

    De maître à travailleur:

     worker.send({json data}); // In Master part process.on('message', yourCallbackFunc(jsonData)); // In Worker part 

    D’ouvrier à maître:

     process.send({json data}); // In Worker part worker.on('message', yourCallbackFunc(jsonData)); // In Master part 

    J’espère que vous pourrez ainsi envoyer et recevoir des données dans les deux sens. Marquez-le comme une réponse si vous le trouvez utile afin que d’autres utilisateurs puissent également trouver la réponse. Merci

    Si l’access en lecture seule convient à votre application, essayez mon propre module de mémoire partagée . Il utilise mmap sous les couvertures, les données sont donc chargées au fur et à mesure de leur access, et non en une La mémoire est partagée entre tous les processus de la machine. Utiliser c’est super facile:

     const Shared = require('mmap-object') const shared_object = new Shared.Open('table_file') console.log(shared_object.property) 

    Il vous donne une interface d’object standard avec un magasin de chaînes de clés ou de nombres et de valeurs. C’est super rapide dans mes applications.

    Une version expérimentale en lecture-écriture du module est également disponible pour les tests.

    Dans node.js, fork ne fonctionne pas comme en C ++. Il ne s’agit pas d’une copie de l’état actuel du processus, mais d’un nouveau processus. Donc, dans ce cas, les variables ne sont pas partagées. Chaque ligne de code fonctionne pour chaque processus, mais le processus maître a l’indicateur cluster.isMaster défini sur true. Vous devez charger vos données pour chaque processus de travail. Faites attention si vos données sont vraiment énormes, car chaque processus aura sa propre copie. Je pense que vous devez interroger des parties de données dès que vous en avez besoin ou attendre si vous en avez réellement besoin en mémoire.

    Vous pouvez utiliser Redis.

    Redis est une source ouverte, un cache et un magasin clé-valeur sous licence BSD. Il est souvent appelé serveur de structure de données car les clés peuvent contenir des chaînes, des hachages, des listes, des ensembles, des ensembles sortingés, des bitmaps et des hyperloglogs.

    redis.io