Home  >  Article  >  Web Front-end  >  Introduction to the implementation principles of RPC (remote procedure call) in node.js_node.js

Introduction to the implementation principles of RPC (remote procedure call) in node.js_node.js

WBOY
WBOYOriginal
2016-05-16 16:29:002589browse

I just came into contact with RPC (remote procedure call), which is a method that can call a program on a remote machine locally. I saw a simple nodejs implementation, which is very good for learning the principles of RPC: nodejs light_rpc

Usage example:

Copy code The code is as follows:

//Server
var light_rpc = require('./index.js');
var port = 5556;
var rpc = new light_rpc({
combine: function(a, b, callback){
         callback(a b);
},
​ multiply: function(t, cb){
         cb(t*2);
}
}).listen(port);

Sample client:

Copy code The code is as follows:

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

Briefly talk about the whole process:

1. The server starts the program, listens to the port, implements the functions called by the client (such as combine and multiply in the above example), and saves them in an object.
2. The client starts the program, connects to the server, and sends the describe command after the connection is completed, asking the server to return the function name it can provide for calling.

Copy code The code is as follows:

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

3. The server receives the describe command, wraps its callable function name and sends it out ("combine", "multiply")
4. The client receives the function name sent by the server, registers it in its own object, and wraps a method for each function name, so that when calling these functions locally, it actually sends a request to the server:

Copy code The code is as follows:

for(var p in cmd.data){
remoteObj[p] = getRemoteCallFunction(p, self.callbacks, connection);
//The implementation of getRemoteCallFunction is shown below
}

5. The client calls the server-side function:

1) Generate a unique ID for the incoming callback function, called callbackId, and record it in an object of the client.
2) Package the following data and send it to the server: calling function name, JSON serialized parameter list, callbackId

Copy code The code is as follows:

function getRemoteCallFunction(cmdName, callbacks, connection){
return function(){
var id = uuid.generate();
If(typeof arguments[arguments.length-1] == 'function'){
​​ callbacks[id] = arguments[arguments.length-1];
}
var args = parseArgumentsToArray.call(this, arguments);
var newCmd = command(cmdName, {id: id, args: args});
Connection.write(newCmd);
}
}

6. The server receives the above information, parses the data, deserializes the parameter list, and calls the function according to the function name and parameters.

Copy code The code is as follows:

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

7. After the function is completed, serialize the result and send it back to the client together with the previously received callbackId

Copy code The code is as follows:

function getSendCommandBackFunction(connection, cmdId){
return function(){
var innerArgs = parseArgumentsToArray.call({}, arguments);
var resultCommand = command(resultCmd, {id: cmdId, args: innerArgs});
Connection.write(resultCommand);
};
}

8. The client receives the function operation result and callbackId, takes out the callback function based on the callbackId, and passes the operation result into the callback function for execution.

9. The entire process is completed, please see the source code for details: https://github.com/romulka/nodejs-light_rpc

A few points to note:

1. The client and server remain connected during the entire process. Unlike the http protocol, the connection is disconnected after sending and receiving. Therefore, the completion of a data transmission cannot be judged by disconnecting the connection. In order to judge the completion of data reception, the data sent by the client and server follows a simple protocol: add the length of the data packet and the delimiter before the data. For example, the delimiter is n: [packet length data], so that after receiving the data, first take out the length of the data packet, and then continuously judge whether the accumulated data packets received are equal to or exceed this length. If so, one data transmission is completed, and you can start parsing and extracting the data.

2. This RPC is simple because it does not consider the function type in the parameters. For example, if the parameter is an object and there are function members under this object, the function will be ignored during JSON serialization, and this function cannot be executed on the server side. of.

To solve this problem, complex processing is required:

1. Deeply traverse each parameter to be sent to the remote end, extract the function members, generate a unique ID for this function, put it into a local object, replace this function member with this id string, and identify it This member is actually a function. In this way, the object can be serialized and sent out.
2. The server receives the call. When it wants to use the function in the parameter object, it determines that this is a function that has been processed by the client and has an id. It sends the id back to the client and uses the same method to set its own callback function. Pass the id to the client and wait for the callback from the client.
3. The client receives the function id, finds the function entity, calls it, and after completion, sends it back to the server according to the callback id given by the server
4. The server receives the result, finds the callback function, continues execution, and completes.

The recording method of functions can be completed in other ways. The general idea is to replace the function with something that can be serialized, and record the function so that the function can be found locally when called by the remote side. You can refer to the implementation of dnode.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn