Maison  >  Article  >  interface Web  >  Explication détaillée de l'implémentation des nœuds de la mémoire partagée du cluster

Explication détaillée de l'implémentation des nœuds de la mémoire partagée du cluster

小云云
小云云original
2018-01-20 10:53:161689parcourir

Cet article présente principalement comment le nœud utilise la communication de processus pour réaliser la mémoire partagée du cluster. L'éditeur pense que c'est plutôt bien, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur et jetons un œil. J'espère que cela pourra aider tout le monde.

L'API standard de Node.js ne fournit pas de mémoire partagée par les processus. Cependant, grâce à la méthode d'envoi de l'interface IPC et à la surveillance des événements de message, un mécanisme de collaboration entre plusieurs processus peut être réalisé via la communication. .Exploiter la mémoire partagée.

##Utilisation de base d'IPC :


// worker进程 发送消息
process.send(‘读取共享内存');
 
// master进程 接收消息 -> 处理 -> 发送回信
cluster.on('online', function (worker) {
   // 有worker进程建立,即开始监听message事件
   worker.on(‘message', function(data) {
     // 处理来自worker的请求
     // 回传结果
     worker.send(‘result')
   });
});

Dans Node.js, via send et sur The La communication IPC mise en œuvre par (« message », rappel) possède plusieurs fonctionnalités. Tout d'abord, le maître et les travailleurs peuvent communiquer entre eux, mais les travailleurs ne peuvent pas communiquer directement entre eux, mais les travailleurs peuvent communiquer indirectement via le transfert principal. De plus, les données transmises via la méthode d'envoi seront traitées par JSON.stringify avant d'être transmises. Après avoir été reçues, elles seront analysées à l'aide de JSON.parse. Par conséquent, l'objet Buffer deviendra un tableau après avoir été transmis, mais la fonction ne peut pas être transmise directement. D'un autre côté, tous les types de données, à l'exception du tampon et de la fonction, peuvent être transférés directement (ce qui est déjà très puissant, et le tampon et la fonction peuvent également être transférés en utilisant des méthodes alternatives).

Sur la base des caractéristiques ci-dessus, nous pouvons concevoir une solution pour partager la mémoire via IPC :

1 En tant qu'utilisateur de mémoire partagée, le processus de travail n'exploite pas directement la mémoire partagée, mais. via send La méthode informe le processus maître d'effectuer une opération d'écriture (set) ou de lecture (get).

2. Le processus maître initialise un objet Objet en tant que mémoire partagée, et lit et écrit la valeur clé de l'Objet en fonction du message envoyé par le travailleur.

3. Étant donné que la communication entre processus est utilisée, les opérations set et get initiées par le travailleur sont des opérations asynchrones. Le maître effectue des opérations de lecture et d'écriture réelles en fonction de la demande, puis renvoie les résultats au travailleur (. c'est-à-dire qu'il envoie les données de résultat au travailleur).

##Format des données

Afin de réaliser des fonctions de lecture et d'écriture asynchrones entre les processus, le format des données de communication doit être standardisé.

Le premier concerne les données de la demande du travailleur :


requestMessage = {
  isSharedMemoryMessage: true, // 表示这是一次共享内存的操作通信
  method: ‘set', // or ‘get' 操作的方法
  id: cluster.worker.id, // 发起操作的进程(在一些特殊场景下,用于保证master可以回信)
  uuid: uuid, // 此次操作的(用于注册/调用回调函数)
  key: key, // 要操作的键
  value: value // 键对应的值(写入)
}

Après avoir reçu les données, le maître effectuera les opérations correspondantes selon la méthode, et puis selon requestMessage.id Envoyez les données de résultat au travailleur correspondant. Le format des données est le suivant :


responseMessage = {
  isSharedMemoryMessage: true, // 标记这是一次共享内存通信
  uuid: requestMessage.uuid, // 此次操作的唯一标示
  value: value // 返回值。get操作为key对应的值,set操作为成功或失败
}

L'importance de standardiser le format des données est la suivante. le maître peut envoyer les résultats du traitement après avoir reçu la demande au travailleur correspondant, et après avoir reçu le résultat renvoyé, le travailleur peut appeler le rappel correspondant à cette communication pour réaliser une collaboration.

Après avoir standardisé le format des données, la prochaine chose à faire est de concevoir deux ensembles de codes, respectivement pour le processus maître et le processus de travail, pour surveiller la communication et traiter les données de communication afin de réaliser la fonction de mémoire partagée.

##Classe User

Les instances de la classe User fonctionnent dans le processus de travail et sont chargées d'envoyer des requêtes pour faire fonctionner la mémoire partagée et d'écouter les réponses du maître.


var User = function() {
  var self = this;
  self.__uuid__ = 0;
 
  // 缓存回调函数
  self.__getCallbacks__ = {};
 
  // 接收每次操作请求的回信
  process.on('message', function(data) {
    
    if (!data.isSharedMemoryMessage) return;
    // 通过uuid找到相应的回调函数
    var cb = self.__getCallbacks__[data.uuid];
    if (cb && typeof cb == 'function') {
      cb(data.value)
    }
    // 卸载回调函数
    self.__getCallbacks__[data.uuid] = undefined;
  });
};
 
// 处理操作
User.prototype.handle = function(method, key, value, callback) {
 
  var self = this;
  var uuid = self.__uuid__++;
 
  process.send({
    isSharedMemoryMessage: true,
    method: method,
    id: cluster.worker.id,
    uuid: uuid,
    key: key,
    value: value
  });
 
  // 注册回调函数
  self.__getCallbacks__[uuid] = callback;
 
};
 
User.prototype.set = function(key, value, callback) {
  this.handle('set', key, value, callback);
};
 
User.prototype.get = function(key, callback) {
  this.handle('get', key, null, callback);
};

##Classe Manager

Les instances de la classe Manager fonctionnent dans le processus maître et sont utilisées pour initialiser un Objet en tant que mémoire partagée et, selon la demande de l'instance utilisateur, ajoute des paires clé-valeur dans la mémoire partagée ou lit la valeur clé, puis renvoie le résultat.


var Manager = function() {
 
  var self = this;
  
  // 初始化共享内存
  self.__sharedMemory__ = {};
    
  // 监听并处理来自worker的请求
  cluster.on('online', function(worker) {
    worker.on('message', function(data) {
      // isSharedMemoryMessage是操作共享内存的通信标记
      if (!data.isSharedMemoryMessage) return;
      self.handle(data);
    });
  });
};
 
Manager.prototype.handle = function(data) {
  var self = this;
  var value = this[data.method](data);
 
  var msg = {
    // 标记这是一次共享内存通信
    isSharedMemoryMessage: true,       
    // 此次操作的唯一标示
    uuid: data.uuid,
    // 返回值
    value: value
  };
 
  cluster.workers[data.id].send(msg);
};
 
// set操作返回ok表示成功
Manager.prototype.set = function(data) {
  this.__sharedMemory__[data.key] = data.value;
  return 'OK';
};
 
// get操作返回key对应的值
Manager.prototype.get = function(data) {
  return this.__sharedMemory__[data.key];
};

## Comment utiliser


if (cluster.isMaster) {
 
  // 初始化Manager的实例
  var sharedMemoryManager = new Manager();
 
  // fork第一个worker
  cluster.fork();
 
  // 1秒后fork第二个worker
  setTimeout(function() {
    cluster.fork();
  }, 1000);
   
} else {
 
  // 初始化User类的实例
  var sharedMemoryUser = new User();
 
  if (cluster.worker.id == 1) {
    // 第一个worker向共享内存写入一组数据,用a标记
    sharedMemoryUser.set('a', [0, 1, 2, 3]);
  }
 
  if (cluster.worker.id == 2) {
    // 第二个worker从共享内存读取a的值
    sharedMemoryUser.get('a', function(data) {
      console.log(data); // => [0, 1, 2, 3]
    });
  }
  
}

Ce qui précède est a pass La fonction de mémoire partagée multi-processus implémentée par la communication IPC. Il convient de noter que cette méthode met les données en cache directement dans la mémoire du processus maître. Vous devez faire attention à l'utilisation de la mémoire. Vous pouvez envisager d'ajouter ici quelques stratégies d'élimination simples. pour optimiser l'utilisation de la mémoire. De plus, si les données lues et écrites en une seule fois sont relativement volumineuses, le temps de communication IPC augmentera également en conséquence.

Code complet : https://github.com/x6doooo/sharedmemory

Recommandations associées :

À propos de laravel5.2 et redis_cluster Introduction à la configuration

Construction de cluster MySQL-Cluster (basée sur la compilation manuelle des packages d'installation) Explication détaillée

Introduction détaillée à la communication en mémoire partagée

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn