RPC的nodejs简单实现
来源:互联网 发布:格兰杰詹姆斯数据 编辑:程序博客网 时间:2024/05/01 06:59
使用示例:
//服务端
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取出回调函数,把运行结果传入回调函数中执行。
self.callbacks[cmd.data.id].apply(
this
, cmd.data.args);
9.整个过程完成,详见源码:https://github.com/romulka/nodejs-light_rpc
几个注意的点:
1.整个过程中client和server一直保持连接,不像http协议发送和接收完就断开链接,所以不能以断开链接判断一次数据的传送完成。为了判断数据接收完成,client和server发送的数据遵循一个简单的协议:在数据前加上数据包的长度和分隔符,如定分隔符为\n:[数据包长度\n数据],这样在收到数据后首先取出数据包的长度,再不断判断累计已接收到的数据包是否等于或超过这个长度,若是则一次数据传送完成,可以开始解析提取数据。
2.这个RPC简单在于没有考虑参数里有函数类型的情况,例如有参数是一个object,这个object下有函数成员,JSON序列化时会把函数忽略,在server端是执行不了这个函数的。
为了解决这个问题,需要进行复杂的处理:
- 深度遍历每个要发送给远端的参数,把函数成员抽出来,给这个函数生成唯一id,放到本地一个对象里,把这个函数成员替换成这个id字符串,并标识这个成员实际上是一个函数。这样这个对象就可以序列化发送出去了。
- server接收到调用,当要使用参数object里的函数时,判断到这是一个经过client处理过的函数,有一个id,把这个id发送回client端,并用同样的方法把自身的回调函数id传给client,等待client端的回调。
- client端接收到这个函数id,找到这个函数实体,调用,完成后根据server端给的回调id发送回给server端
- server端收到结果,找到回调函数,继续执行,完成。
原文转载至:http://blog.cnbang.net/tech/1966/
- RPC的nodejs简单实现
- 简单的RPC实现
- 简单实现的RPC
- 简单的RPC java实现
- 简单的RPC java实现
- 简单的RPC java实现
- 简单的RPC java实现
- 自己实现简单的RPC
- 一个简单的nodeJS实现
- 一个简单的rpc框架的实现
- 一个简单的rpc框架的实现
- 最简单的Rpc框架的实现
- 简单的RPC框架的实现
- 简单层RPC应用的Java实现
- 非常有用:简单的RPC java实现
- 基于TCP的RPC简单实现
- Zookeeper实现简单的分布式RPC框架
- Java实现简单的RPC框架
- 智能.追本数源 -- 第二届『数据驱动大会』
- 倾斜45TextView
- LINUX系统目录表格
- Android Studio项目窗口操作小技巧
- npm install -g @angular/cli@latest 失败
- RPC的nodejs简单实现
- ReLU为什么比Sigmoid效果好
- 硬币问题2.2(1)
- 线性代数中的范数
- 【BZOJ1231】[Usaco2008 Nov]mixup2 混乱的奶牛 状压DP
- 网络请求以及方法优化Jersey
- Android中完全退出应用程序
- 机器学习中的范数规则化之(一)L0、L1与L2范数
- Hive查询