当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    node.js中RPC(远程过程调用)的实现原理介绍

    栏目:win服务器问题汇总 时间:2020-01-13 14:22

    刚接触到RPC(远程过程调用),就是可以在本地调用远程机子上的程序的方法,看到一个简单的nodejs实现,用来学习RPC的原理很不错:nodejs light_rpc

    使用示例:

    复制代码 代码如下:
    //服务端
    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:

    复制代码 代码如下:
    //客户端
    rpc.connect(5556, 'localhost', function(remote, conn){
        remote.combine(1, 2, function(res){
            if(res != 3){
                console.log('ERROR', res);
            }
        });
    });

    简单说说整个过程:

    1.server端启动程序,侦听端口,实现提供给client调用的函数(如上述例子的combine和multiply),保存在一个对象里。
    2.client端启动程序,连接服务端,连接完成后发送describe命令,要求server返回它能提供调用的函数名。

    复制代码 代码如下:
    connection.on('connect', function(){
      connection.write(command(descrCmd));
    });

    3.server端接收到describe命令,把自己可供调用的函数名包装好发送出去(“combine”, “multiply”)
    4.client端接收到server发送的函数名,注册到自己的对象里,给每个函数名包装一个方法,使本地调用这些函数时实际上是向server端发送请求:

    复制代码 代码如下:
    for(var p in cmd.data){
      remoteObj[p] = getRemoteCallFunction(p, self.callbacks, connection);
      //getRemoteCallFunction的实现见下面
    }

    5.client端调用server端的函数:

    1) 给传入的callback函数生成一个唯一ID,称为callbackId,记录到client的一个对象里。
    2) 包装好以下数据发送给server端:调用函数名,JSON序列化后的参数列表,callbackId

    复制代码 代码如下:
    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.server端接收到上述信息,解析数据,对参数列表反序列化,根据函数名和参数调用函数。

    复制代码 代码如下:
    var args = cmd.data.args;
    args.push(getSendCommandBackFunction(c, cmd.data.id));
    self.wrapper[cmd.command].apply({}, args);

    7.函数运行完成后,把结果序列化,连同之前收到的callbackId发送回client端