Ich kam gerade mit RPC (Remote Procedure Call) in Kontakt, eine Methode, mit der Programme auf Remote -Maschinen lokal aufgerufen werden können. Ich habe eine einfache NodeJS -Implementierung gesehen, die sehr gut zum Lernen des Prinzips von RPC: NodeJS Light_RPC ist
Beispiel der Nutzung:
Die Codekopie lautet wie folgt:
// Serverseite
var light_rpc = required ('./ index.js');
var port = 5556;
var rpc = new light_rpc ({{
Kombinieren Sie: Funktion (a, b, callback) {
Rückruf (a + b);
},
Multiplizieren Sie: Funktion (t, cb) {
CB (t*2);
}
}). Hören (Port);
Beispiel Client:
Die Codekopie lautet wie folgt:
// Client
rpc.connect (5556, 'localhost', function (remote, conn) {
remote.combine (1, 2, function (res) {
if (res! = 3) {
console.log ('error', res);
}
});
});
Lassen Sie uns kurz über den gesamten Prozess sprechen:
1. Die Serverseite startet das Programm, hört den Port an, implementiert die dem Client bereitgestellten Funktionen (z. B. kombinieren und multiplizieren im obigen Beispiel) und speichert sie in einem Objekt.
2. Die Client -Seite startet das Programm, stellt eine Verbindung zum Server her und sendet einen Beschreibungsbefehl nach Abschluss der Verbindung, sodass der Server den für den Anruf angegebenen Funktionsnamen zurückgeben kann.
Die Codekopie lautet wie folgt:
Connection.on ('Connect', function () {
Connection.Write (Befehl (Descrcmd));
});
3. Die Serverseite empfängt den Befehl beschreiben, wickelt den Funktionsnamen, den er anrufen kann, und sendet ihn aus ("kombinieren", "multiplizieren").
V.
Die Codekopie lautet wie folgt:
für (var p in cmd.data) {
remoteobj [p] = getremoteCallfunction (p, self.callbacks, Verbindung);
// Die Implementierung von GetRemoteCallfunction ist unten gezeigt
}
5. Die Client -Seite ruft die Server -Seitenfunktionen auf:
1) Generieren Sie eine eindeutige ID für die übergebene Rückruffunktion, die als CallbackID bezeichnet wird, und zeichnen Sie sie in einem Objekt des Clients auf.
2) Verpacken Sie die folgenden Daten und senden
Die Codekopie lautet wie folgt:
Funktion getremoteCallfunction (CMDName, Callbacks, Verbindung) {
return function () {
var id = uUid.generate ();
if (typeof argumente [argumente.length-1] == 'Funktion') {
Rückrufe [ID] = Argumente [Argumente.Length-1];
}
var args = parSeargumentStoArray.call (this, Argumente);
var newcmd = command (cmdname, {id: id, args: args});
Connection.Write (NewCMD);
}
}
6. Die Serverseite empfängt die oben genannten Informationen, analysiert die Daten, deserialisiert die Parameterliste und ruft die Funktion gemäß dem Funktionsnamen und den Parametern auf.
Die Codekopie lautet wie folgt:
var args = cmd.data.args;
args.push (GetendCommandbackfunction (c, cmd.data.id));
self.wrapper [cmd.command] .Apply ({}, args);
7. Nach Abschluss der Funktion serialisieren Sie das Ergebnis und senden Sie es zusammen mit der Callbackid -ID, die ich zuvor erhalten habe, wieder an die Client -Seite.
Die Codekopie lautet wie folgt:
Funktion getendCommandbackfunction (Verbindung, cmdid) {
return function () {
var innerargs = parseargumentStoArray.call ({}, Argumente);
var resultCommand = command (resultcmd, {id: cmdid, args: Innerargs});
connection.write (resultcommand);
};
}
8. Die Client -Seite empfängt das Funktionsumlauf und das CallbackID, nimmt die Rückruffunktion basierend auf CallbackID heraus und übergibt das Run -Ergebnis in die Rückruffunktion für die Ausführung.
9. Der gesamte Vorgang ist abgeschlossen. Weitere Informationen finden Sie im Quellcode: https://github.com/romulka/nodejs-light_rpc
Ein paar Notizen:
1. Der Client und der Server sind während des gesamten Prozesses immer verbunden, im Gegensatz zum HTTP -Protokoll, das den Link nach dem Senden und Empfangen trennen, kann die Trennung nicht verwendet werden, um festzustellen, ob die Datenübertragung durch Trennen abgeschlossen wird. Um festzustellen, dass der Datenempfang abgeschlossen ist, folgen die vom Client und dem Server gesendeten Daten einem einfachen Protokoll: Fügen Sie die Länge des Datenpakets und den Trennzeichen vor den Daten hinzu, wie z. Auf diese Weise wird nach Empfang der Daten zuerst die Länge des Datenpakets abgerufen und dann kontinuierlich bestimmen, ob die akkumulierten empfangenen Datenpakete dieser Länge gleich oder überschreiten. In diesem Fall wird die Datenübertragung abgeschlossen und die Daten können analysiert und extrahiert werden.
2. Das einfachste RPC ist, dass er den Funktionstyp im Parameter nicht berücksichtigt. Wenn beispielsweise ein Parameter ein Objekt ist, gibt es unter diesem Objekt Funktionselemente. Wenn JSON serialisiert, wird die Funktion ignoriert und diese Funktion kann nicht auf der Serverseite ausgeführt werden.
Um dieses Problem zu lösen, ist eine komplexe Verarbeitung erforderlich:
1. Tief über jeden Parameter an das Remote -Ende gesendet, das Funktionselement extrahieren, eine eindeutige ID für diese Funktion generieren, in ein lokales Objekt einfügen, das Funktionselement durch diese ID -Zeichenfolge ersetzen und feststellen, dass dieses Mitglied tatsächlich eine Funktion ist. Auf diese Weise kann das Objekt serialisiert und gesendet werden.
2. Wenn der Server einen Aufruf empfängt, wenn er die Funktion im Parameterobjekt verwenden möchte, wird festgelegt, dass dies eine vom Client verarbeitete Funktion mit einer ID ist, diese ID an den Client zurücksenden und die Callback -Funktions -ID auf die gleiche Weise an den Client weitergeben und auf den Rückruf auf der Client -Seite warten.
3. Die Client -Seite empfängt diese Funktions -ID, findet diese Funktion Entität, ruft sie an und sendet sie gemäß der von der Serverseite angegebenen Rückruf -ID an die Serverseite zurück.
4. Die Serverseite empfängt das Ergebnis, findet die Rückruffunktion, führt weiterhin aus und vervollständigt.
Die Aufzeichnungsmethode einer Funktion kann auf andere Weise ausgeführt werden. Die allgemeine Idee besteht darin, die Funktion durch etwas Serialisierbares zu ersetzen, damit die Funktion lokal gefunden werden kann, wenn sie auf der Fernseite aufgerufen werden. Sie können auf die Implementierung von DNODE verweisen.