Maison  >  Article  >  interface Web  >  Introduction aux principes d'implémentation du RPC (appel de procédure à distance) dans node.js_node.js

Introduction aux principes d'implémentation du RPC (appel de procédure à distance) dans node.js_node.js

WBOY
WBOYoriginal
2016-05-16 16:29:002624parcourir

Je viens d'entrer en contact avec RPC (remote procédure call), qui est une méthode qui permet d'appeler localement un programme sur une machine distante, j'ai vu une implémentation simple de nodejs, qui est très bien pour apprendre les principes de RPC : nodejs light_rpc

Exemple d'utilisation :

Copier le code Le code est le suivant :

//Serveur
var light_rpc = require('./index.js');
port var = 5556;
var rpc = nouveau light_rpc({
combiner : fonction (a, b, rappel){
         rappel(a b);
},
​ multiplier : fonction(t, cb){
         cb(t*2);
>
}).écouter(port);

Exemple de client :

Copier le code Le code est le suivant :

//Client
rpc.connect(5556, 'localhost', function(remote, conn){
Remote.combine(1, 2, function(res){
Si(res != 3){
console.log('ERREUR', res);
>
});
});

Parlez brièvement de l'ensemble du processus :

1. Le serveur démarre le programme, écoute le port, implémente les fonctions appelées par le client (telles que combiner et multiplier dans l'exemple ci-dessus) et les enregistre dans un objet.
2. Le client démarre le programme, se connecte au serveur et envoie la commande décrire une fois la connexion terminée, demandant au serveur de renvoyer le nom de fonction qu'il peut fournir pour l'appel.

Copier le code Le code est le suivant :

connexion.on('connect', function(){
connexion.write(command(descrCmd));
});

3. Le serveur reçoit la commande décrire, encapsule son nom de fonction appelable et l'envoie ("combiner", "multiplier")
4. Le client reçoit le nom de fonction envoyé par le serveur, l'enregistre dans son propre objet et encapsule une méthode pour chaque nom de fonction, de sorte que lors de l'appel de ces fonctions localement, il envoie réellement une requête au serveur :

Copier le code Le code est le suivant :

pour(var p dans cmd.data){
remoteObj[p] = getRemoteCallFunction(p, self.callbacks, connection);
//L'implémentation de getRemoteCallFunction est présentée ci-dessous
>

5. Le client appelle la fonction côté serveur :

1) Générez un identifiant unique pour la fonction de rappel entrant, appelé callbackId, et enregistrez-le dans un objet du client.
2) Regroupez les données suivantes et envoyez-les au serveur : nom de la fonction appelante, liste de paramètres sérialisés JSON, callbackId

Copier le code Le code est le suivant :

function getRemoteCallFunction(cmdName, rappels, connexion){
fonction de retour(){
var identifiant = uuid.generate();
Si (type d'arguments [arguments.length-1] == 'fonction'){
​​ rappels[id] = arguments[arguments.length-1];
>
var args = parseArgumentsToArray.call(this, arguments);
var newCmd = command(cmdName, {id : id, args : args});
Connection.write(newCmd);
>
>

6. Le serveur reçoit les informations ci-dessus, analyse les données, désérialise la liste des paramètres et appelle la fonction en fonction du nom de la fonction et des paramètres.

Copier le code Le code est le suivant :

var args = cmd.data.args;
args.push(getSendCommandBackFunction(c, cmd.data.id));
self.wrapper[cmd.command].apply({}, args);

7. Une fois la fonction terminée, sérialisez le résultat et renvoyez-le au client avec le callbackId précédemment reçu

Copier le code Le code est le suivant :

fonction getSendCommandBackFunction (connexion, cmdId){
fonction de retour(){
var innerArgs = parseArgumentsToArray.call({}, arguments);
var resultCommand = command(resultCmd, {id : cmdId, args : innerArgs});
Connection.write(resultCommand);
};
>

8. Le client reçoit le résultat de l'opération de fonction et le callbackId, retire la fonction de rappel basée sur le callbackId et transmet le résultat de l'opération dans la fonction de rappel pour exécution.

9. L'ensemble du processus est terminé, veuillez consulter le code source pour plus de détails : https://github.com/romulka/nodejs-light_rpc

Quelques points à noter :

1. Le client et le serveur restent connectés pendant tout le processus. Contrairement au protocole http, la connexion est déconnectée après l'envoi et la réception. Par conséquent, la fin d'une transmission de données ne peut pas être jugée en déconnectant la connexion. Afin de juger de l'achèvement de la réception des données, les données envoyées par le client et le serveur suivent un protocole simple : ajoutez la longueur du paquet de données et le délimiteur avant les données. Par exemple, le délimiteur est n : [longueur du paquet. data], de sorte qu'après avoir reçu les données, retirez d'abord la longueur du paquet de données, puis jugez en continu si les paquets de données accumulés reçus sont égaux ou supérieurs à cette longueur. Si tel est le cas, une transmission de données est terminée et vous pouvez. commencez à analyser et à extraire les données.

2. Ce RPC est simple car il ne prend pas en compte le type de fonction dans les paramètres. Par exemple, si le paramètre est un objet et qu'il y a des membres de fonction sous cet objet, la fonction sera ignorée lors de la sérialisation JSON, et ce. La fonction ne peut pas être exécutée côté serveur.

Pour résoudre ce problème, un traitement complexe est nécessaire :

1. Parcourez profondément chaque paramètre à envoyer à l'extrémité distante, extrayez les membres de la fonction, générez un identifiant unique pour cette fonction, placez-le dans un objet local, remplacez ce membre de la fonction par cette chaîne d'identification et identifiez-le. le membre est en fait une fonction. De cette façon, l'objet peut être sérialisé et envoyé.
2. Le serveur reçoit l'appel. Lorsqu'il souhaite utiliser la fonction dans l'objet paramètre, il détermine qu'il s'agit d'une fonction qui a été traitée par le client et qui possède un identifiant. Il renvoie l'identifiant au client et utilise l'identifiant. même méthode pour définir sa propre fonction de rappel. Transmettez l'identifiant au client et attendez le rappel du client.
3. Le client reçoit l'identifiant de fonction, trouve l'entité de fonction, l'appelle et, une fois terminé, la renvoie au serveur en fonction de l'identifiant de rappel donné par le serveur
4. Le serveur reçoit le résultat, trouve la fonction de rappel, poursuit l'exécution et termine.

La méthode d'enregistrement des fonctions peut être complétée par d'autres manières. L'idée générale est de remplacer la fonction par quelque chose qui peut être sérialisé et d'enregistrer la fonction afin que la fonction puisse être trouvée localement lorsqu'elle est appelée par le côté distant. Vous pouvez vous référer à l'implémentation de dnode.

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