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

 更新时间:2014年12月05日 13:19:01   投稿:junjie  
这篇文章主要介绍了node.js中RPC(远程过程调用)的实现原理介绍,本文基于一个简单的RPC库nodejs light_rpc实现,需要的朋友可以参考下

刚接触到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端

复制代码 代码如下:

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

8.client端接收到函数运行结果和callbackId,根据callbackId取出回调函数,把运行结果传入回调函数中执行。

9.整个过程完成,详见源码:https://github.com/romulka/nodejs-light_rpc

几个注意的点:

1.整个过程中client和server一直保持连接,不像http协议发送和接收完就断开链接,所以不能以断开链接判断一次数据的传送完成。为了判断数据接收完成,client和server发送的数据遵循一个简单的协议:在数据前加上数据包的长度和分隔符,如定分隔符为\n:[数据包长度\n数据],这样在收到数据后首先取出数据包的长度,再不断判断累计已接收到的数据包是否等于或超过这个长度,若是则一次数据传送完成,可以开始解析提取数据。

2.这个RPC简单在于没有考虑参数里有函数类型的情况,例如有参数是一个object,这个object下有函数成员,JSON序列化时会把函数忽略,在server端是执行不了这个函数的。

为了解决这个问题,需要进行复杂的处理:

1.深度遍历每个要发送给远端的参数,把函数成员抽出来,给这个函数生成唯一id,放到本地一个对象里,把这个函数成员替换成这个id字符串,并标识这个成员实际上是一个函数。这样这个对象就可以序列化发送出去了。
2.server接收到调用,当要使用参数object里的函数时,判断到这是一个经过client处理过的函数,有一个id,把这个id发送回client端,并用同样的方法把自身的回调函数id传给client,等待client端的回调。
3.client端接收到这个函数id,找到这个函数实体,调用,完成后根据server端给的回调id发送回给server端
4.server端收到结果,找到回调函数,继续执行,完成。

函数的记录方法可以以其他方式完成,大体思路就是把函数替换成可序列化的东西,记录函数以便remote端调用时能在本地找到这个函数。可以参考dnode的实现。

相关文章

  • Nodejs进阶:核心模块net入门学习与实例讲解

    Nodejs进阶:核心模块net入门学习与实例讲解

    本篇文章主要是介绍了Nodejs之NET模块,net模块是同样是nodejs的核心模块,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-11-11
  • node.js中的console.assert方法使用说明

    node.js中的console.assert方法使用说明

    这篇文章主要介绍了node.js中的console.assert方法使用说明,本文介绍了console.assert的方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下
    2014-12-12
  • centos 上快速搭建ghost博客方法分享

    centos 上快速搭建ghost博客方法分享

    本文给大家分享的是如何在centos上快速搭建基于Node.js 构建的开源博客平台ghost的方法,非常的实用,有需要的小伙伴可以参考下
    2018-05-05
  • Node处理CPU密集型任务有哪些方法

    Node处理CPU密集型任务有哪些方法

    这篇文章主要介绍了Node处理CPU密集型任务有哪些方法,Node是一个非阻塞I/O和事件驱动的JavaScript运行环境,所以它非常适合用来构建I/O密集型应用,例如Web服务等
    2022-09-09
  • node.js连接MongoDB数据库的2种方法教程

    node.js连接MongoDB数据库的2种方法教程

    这几天一直在学习mongdb的基础知识,跟着网上大神的脚步(代码)去模拟连接mongodb数据库,下面这篇文章就给大家总结介绍了node.js连接MongoDB数据库的2种方法教程,文中介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-05-05
  • koa-router源码学习小结

    koa-router源码学习小结

    这篇文章主要介绍了koa-router源码学习小结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • 手把手带你安装多个node版本

    手把手带你安装多个node版本

    在项目开发过程中,不同项目使用的node版本不同,有时会因为node版本过高或太低,导致报错,下面这篇文章主要给大家介绍了关于安装多个node版本的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • Node.js Streams文件读写操作详解

    Node.js Streams文件读写操作详解

    如果你在处理应用中 I/O 相关的操作,你可以利用 Node.js 中的流(stream),这篇文章主要为大家详细介绍了Node.js Streams文件读写操作,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • 使用 Node-RED对 MQTT 数据流处理

    使用 Node-RED对 MQTT 数据流处理

    本文将介绍使用 Node-RED 连接到 MQTT 服务器,并对 MQTT 数据进行过滤和处理后再将其发送至 MQTT 服务器的完整操作流程。读者可以快速了解如何使用 Node-RED 对 MQTT 数据进行简单的流处理
    2022-05-05
  • Nodejs中怎么实现函数的串行执行

    Nodejs中怎么实现函数的串行执行

    今天小编就为大家分享一篇关于Nodejs中怎么实现函数的串行执行,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论