前面一篇介绍过server,我们来看看对应的client部分。
其实网上有前辈已经很详细的介绍过。我大致也看过,这里记录主要是为了整理自己思路吧,如果对各位看官偶尔能够有点帮助“感情那想必是挺好的!”
至于调试环境请看我前面的node-inspector的转贴。
事件编程好处是用起来很爽,只要关心相关的evnet就哦了。压根不用写多余的代码。但是看起来,调试起来就麻烦的多。
各种回调看起来无比痛苦。
下面我先介绍大体框架。
启动一个rpc client的步骤如下:
var client = Client.create({routeContext: routeContext, router: routeFunc, context: context}); #1
client.start(function(err) { #2
console.log('rpc client start ok.');
client.addProxies(records); #3
client.addServers(servers); #4
client.proxies.user.test.service.echo(routeParam, 'hello', function(err, resp) { #5
if(err) {
console.error(err.stack);
}
console.log("chenee " + resp); #6
});
});
});
2、启动client,启动过程主要是set一些标志。真正网络连接发生在回调函数里面
3、为client添加proxy,一个proxy对应remote目录。和server端相互对应。(但是,实际上我感觉client只要了解remote目录下面的结果即可,应该不需要完整的和server一模一样的代码。!!!这里总是觉得有些不对劲!!后面有空仔细研究。)
4、添加服务器信息。ip,port。。。
5、真正的rpc调用;
这里由于前面已经挂接好了proxy,所以client.proxies.user.test.service.echo === client.proxies[user][test][servieces][echo]; 其中user,test,services,echo都是动态生成的。
6、rpc的回调函数。resp是server返回的信息。
说明:
1、这里的rpc应该是单向的,不像python的twisted,一旦PB建立好以后,server和client是对等的。
如果需要双向:1 某个app同时建立server和client的实例, 2 改一下这里的实现,client和server保持长连,增加client给server暴露借口。
2、这个是pomelo-rpc自己的sample的流程,按照这个流程一个rpc就实现了。下面我们看具体内部机制。
文件结构如下:
lib/
├── rpc-client
│ ├── client.js
│ ├── mailboxes
│ │ ├── blackhole.js
│ │ ├── tcp-mailbox.js
│ │ └── ws-mailbox.js
│ ├── mailbox.js
│ ├── mailstation.js
│ └── router.js
├── rpc-server
│ ├── acceptor.js
│ ├── acceptors
│ │ ├── tcp-acceptor.js
│ │ └── ws-acceptor.js
│ ├── dispatcher.js
│ ├── gateway.js
│ └── server.js
└── util
├── proxy.js
├── tracer.js
└── utils.js
文件功能分析
1、mailboxes/ws-mailbox.js:这个是mailbox的实现,一个mailbox封装了一个socket.io连接。代表一个client--->server 的逻辑。
2、mailbox.js:是ws-mailbox的factory
3、mailstation.js:是mailbox的管理器。
4、proxy.js:代表一个proxy,主要是利用JS的闭包特性为后面调用这个proxy做铺垫。其实用一个类,然后局部变量也应该可以,并且看上去会更加清晰一些。
5、client.js:操纵mailstation,proxy,并且实现proxy的回调函PorxyCB();这个函数封装给proxy调用,内部实现route功能。这个在sample中由参数传递进来。
至于mailstation的操作,基本就是直接调用。
关键函数、数据结构简介:
1、ws-mailbox.js:中,connect,send
2、mailstation.js:中 dispatch,filter,pending
3、client.js:中ProxyCB
1、因为node是异步的,所以在所有的网络操作,注意一下逻辑链接是通过cb来实现的。比如ws-mailbox中connect,当大家用debuger调试跟踪的时候,这里需要单开一个断点去拦截他的回调。因为他们是逻辑上串行的。
2、mailstation中,所有数据发送都是走dispatch函数,这个函数写的非常精妙,可能需要多看几遍。
2.1、如果mailbox没有初始化:则调用lazyconnect,这个字面就可以了解。然后把发送信息放入pending[]里面,等待链接完成以后再发送。
2.2、如果当前还是正在链接:也是压入pending[];
2.3、对于真正需要发送的数据:我们还需要绕一下filter逻辑。
3、filter:分为before,afterfilter,before是把send()当成回调,after是send()的回调。
before和after都是通过函数递归来实现遍历的。
sample中其实没有用到filter。
4、pending:前面2中已经介绍了。就是用来保存dispatch待处理消息,并且实现异步处理的。而且真正处理的地方是在flushPending(),这个只是在ws-mailbox 中on connect时候回调。
5、ProxyCB:这个是proxy的回调函数,封装了调用一个route的功能。
一个proxy,实际上是对应server的一个remote服务(他们共享同样的remote目录、文件)。分为建立和调用2个部分。这个里ProxyCB负责调用的实现。至于建立,其实和server差不多。但是这里加载的module压根没有被使用。感觉有些浪费。。。。。
client部分整体代码不是很多,但是由于对于这种回调和事件机制比较生疏,所以刚开始看比较累。
总结:
client建立mailstation,mailstation管理mailbox实现网络链接和数据发送。接收。
client和server一样建立一个module并当成参数来建立proxy,使用rpc的时候,就是直接使用这个proxy。
TODO:
还不习惯这个client代码,想动手改改。等后面多看看pomelo,要是还看不惯就自己改一下。open source嘛。。 :)