pomeloコード分析7————pomeloのrpcは分析を実現します.
7895 ワード
どこに書きたいですか?前の穴が邪魔にならないなら、記入しません.へへ~
RPC:remote procedule call;なんですか?言いません.
以下は直接pomeloの実現を見ます.
対応moduleはpomelo-rpcで、これは直接npm installでインストールできます.
例えば、npm install-d pomelo-rpcは、現在のディレクトリのnode_にダウンロードされます.modulesディレクトリの中にあります.
インストール完了後のディレクトリは以下の通りです.
直接に:
まずsampleディレクトリは以下の通りです.
私たちは他の端末にいます.node client.jsで結果が見えます.
libの下に何がありますか?
server.js:落1、モジュールをロードし、モジュールをパラメータとして初期化するgateway.2)ツリー構造を構築し、これらの初期化されたモジュールを登録する
gateway.js:钻初期化acceptorのcalback関数————dispatcher
acceptor.js:菗accepterのfactory、ここではwsタイプだけを生産しているacceptorが死んだと書いてあります.
ws-acceptor.js Swebsocket方式の受信機は具体的に実現される.
登録されたmoduleは、dispatcher.js:Cientが呼び出したツリー構造に基づいて簡単に検索され、moduleを呼び出します.
コードをかき集める:
第一部分:登録して、calbackのツリー構造を生成する.
sample/server.js
このうち、11ギルドはlib/rpc-server/server.jsファイルのcreate関数を呼び出します.以下の通りです.
このgatewayは、loadRemoteServicesによって生成された一連のservicesをパラメータとして受け入れます.
この関数をもう一度見ます.
前に述べたように、すべてのmodule生成作業とexport導出作業は、ロード()関数で完了しました.
10行目の後ろのコードは組織resのためだけです.コードをよく見たり、debugerで印刷したりします.
res[namespace][filename][exports.name]=m[exports.name]
ここはツリーの登録です.後のclientにコールされるのを待っています.
具体的なコールロジックは以下の通りです.
第二部分:起動、トリガロジック
上の第一部はすでにすべてのmoduleを登録しました.server.start()の時は、gateway.start()を呼び出して、さらにaccepter.listen()を呼び出します.
ここのacceptorはws-accptor.jsです.対応部分のコードは以下の通りです.
これはgateway初期化の時にacceptorにかけられたものです.具体的なコードは以下の通りです.
はい、
methode=services[msg.namespace][msg.sevice][msg.method]だけです.
ここのmsg属性は以下の通りです.
namespace:「user」
service:「service」method:「echo」
見ましたよね.上の第一部を登録する時に作った木の形の構造です.
clientが呼び出した時に書いた不一致があると、上記のコードの中でエラー検出部分が淘汰されます.
OK、終了:
まとめ:
第一歩:Serverはツリー型の対応関係を構築する.
そして、clientから渡され、解析されたJSONに基づいてツリー構造に対応する関数を検索して呼び出します.
===========以下にクリエートを見て、
RPC:remote procedule call;なんですか?言いません.
以下は直接pomeloの実現を見ます.
対応moduleはpomelo-rpcで、これは直接npm installでインストールできます.
例えば、npm install-d pomelo-rpcは、現在のディレクトリのnode_にダウンロードされます.modulesディレクトリの中にあります.
インストール完了後のディレクトリは以下の通りです.
AUTHORS index.js lib LICENSE Makefile node_modules package.json README-Chinese.md README.md sample test
実際にpomelo-rpcは他の多くのmoduleに依存しています.具体的にこれらのmoduleは何のために使いますか?これは言いません.自分で見てください直接に:
まずsampleディレクトリは以下の通りです.
sample/
├── client.js
├── remote
│ └── test
│ └── service.js
└── server.js
直接node server.jsは、clientのrpc呼び出しを待つserverを起動することができます.私たちは他の端末にいます.node client.jsで結果が見えます.
libの下に何がありますか?
lib/
├── rpc-client
│ ├── client.js
│ ├── mailboxes
│ │ ├── blackhole.js
│ │ ├── tcp-mailbox.js
│ │ └── ws-mailbox.js
│ ├── mailbox.js
│ ├── mailstation.js
│ └── router.js
├── rpc-server #rpc server
│ ├── acceptor.js # rpc Factory, , ws-acceptor.js, websocket 。
│ ├── acceptors #
│ │ ├── tcp-acceptor.js #tcp
│ │ └── ws-acceptor.js #websocket
│ ├── dispatcher.js #rpc , rpc 。
│ ├── gateway.js # server, start,stop, acceptor callback ———— dispatcher
│ └── server.js #1、 , gateway。2: 。
└── util
├── proxy.js
├── tracer.js
└── utils.js
OK、ファイルからserverの論理タイミングは以下の通りです.server.js:落1、モジュールをロードし、モジュールをパラメータとして初期化するgateway.2)ツリー構造を構築し、これらの初期化されたモジュールを登録する
gateway.js:钻初期化acceptorのcalback関数————dispatcher
acceptor.js:菗accepterのfactory、ここではwsタイプだけを生産しているacceptorが死んだと書いてあります.
ws-acceptor.js Swebsocket方式の受信機は具体的に実現される.
登録されたmoduleは、dispatcher.js:Cientが呼び出したツリー構造に基づいて簡単に検索され、moduleを呼び出します.
コードをかき集める:
第一部分:登録して、calbackのツリー構造を生成する.
sample/server.js
1 var Server = require('..').server;
2
3 debugger;
4 // remote service path info list
5 var paths = [
6 {namespace: 'user', path: __dirname + '/remote/test'} # module, sample 。
7 ];
8
9 var port = 3333;
10
11 var server = Server.create({paths: paths, port: port});
12 server.start();
13 console.log('rpc server started.');
pomeloの中のrpcはパッケージを使って綺麗です.このうち、11ギルドはlib/rpc-server/server.jsファイルのcreate関数を呼び出します.以下の通りです.
module.exports.create = function(opts) {
if(!opts || !opts.port || opts.port < 0 || !opts.paths) {
throw new Error('opts.port or opts.paths invalid.');
}
var services = loadRemoteServices(opts.paths, opts.context);
opts.services = services;
var gateway = Gateway.create(opts);
return gateway;
};
実は一つのserverはgatewayなのです!このgatewayは、loadRemoteServicesによって生成された一連のservicesをパラメータとして受け入れます.
この関数をもう一度見ます.
4 var loadRemoteServices = function(paths, context) {
5 var res = {}, item, m;
6 for(var i=0, l=paths.length; i<l; i++) {
7 item = paths[i];
8 m = Loader.load(item.path, context);
9
10 if(m) {
11 createNamespace(item.namespace, res);
12 for(var s in m) {
13 res[item.namespace][s] = m[s];
14 }
15 }
16 }
17
18 return res;
19 };
20
21 var createNamespace = function(namespace, proxies) {
22 proxies[namespace] = proxies[namespace] || {};
23 };
24
その中のload()前の文章はもう話しました.pomelo-loaderです.だからmは一つのmoduleです.前に述べたように、すべてのmodule生成作業とexport導出作業は、ロード()関数で完了しました.
10行目の後ろのコードは組織resのためだけです.コードをよく見たり、debugerで印刷したりします.
>res
Object
user: Object
service: Object
echo: function (msg, cb) { ...
pomeloは、初期化時に導入されたnamespace、jsモジュールのファイル名、moduleのexports名に基づいて構築され、res[namespace][filename][exports.name]=m[exports.name]
ここはツリーの登録です.後のclientにコールされるのを待っています.
具体的なコールロジックは以下の通りです.
第二部分:起動、トリガロジック
上の第一部はすでにすべてのmoduleを登録しました.server.start()の時は、gateway.start()を呼び出して、さらにaccepter.listen()を呼び出します.
ここのacceptorはws-accptor.jsです.対応部分のコードは以下の通りです.
pro.listen = function(port) {
//check status
if(!!this.inited) {
utils.invokeCallback(this.cb, new Error('already inited.'));
return;
}
this.inited = true;
var self = this;
this.server = sio.listen(port); # 1、 , socket.io listen 。
this.server.set('log level', 0);
this.server.server.on('error', function(err) { # , 。。
self.emit('error', err);
});
this.server.sockets.on('connection', function(socket) { #2、 client ;
self.sockets[socket.id] = socket;
self.emit('connection', {id: socket.id, ip: socket.handshake.address.address});
socket.on('message', function(pkg) { #3、 , “message” ProcessMsgs() 。
try {
if(pkg instanceof Array) {
processMsgs(socket, self, pkg);
} else {
processMsg(socket, self, pkg);
}
} catch(e) {
// socke.io would broken if uncaugth the exception
console.error('rpc server process message error: ' + e);
}
});
socket.on('disconnect', function(reason) { # , 。。。
delete self.sockets[socket.id];
delete self.msgQueues[socket.id];
});
});
this.on('connection', ipFilter.bind(this)); # , 。。。。
if(this.bufferMsg) {
this._interval = setInterval(function() {
flush(self);
}, this.interval);
}
};
上記のコードのコメントを見ると、clientからメッセージが来たら、次の関数を呼び出します.var processMsg = function(socket, acceptor, pkg) {
var tracer = new Tracer(acceptor.rpcLogger, acceptor.rpcDebugLog, pkg.remote, pkg.source, pkg.msg, pkg.traceId, pkg.seqId);
tracer.info('server', __filename, 'processMsg', 'ws-acceptor receive message and try to process message');
acceptor.cb.call(null, tracer, pkg.msg, function() { ##### ##########################
var args = Array.prototype.slice.call(arguments, 0);
for(var i=0, l=args.length; i<l; i++) {
if(args[i] instanceof Error) {
args[i] = cloneError(args[i]);
}
}
。。。。。。。。。。。。。。。。。。。。。。
続いて上に述べました.一旦clientからメッセージがあったら、私達はprocessMsgを呼び出します.プロcessMsgはacceptorのコールバック関数を呼び出します.つまりdispatcher.route関数です.これはgateway初期化の時にacceptorにかけられたものです.具体的なコードは以下の通りです.
this.acceptor = this.acceptorFactory.create(opts, function(tracer, msg, cb) {
dispatcher.route(tracer, msg, self.services, cb);
});
このrouteはいったい何をしていますか?module.exports.route = function(tracer, msg, services, cb) {
tracer.info('server', __filename, 'route', 'route messsage to appropriate service object');
var namespace = services[msg.namespace];
var service = namespace[msg.service];
var method = service[msg.method];
var args = msg.args.slice(0);
args.push(cb);
method.apply(service, args);
};
上のコードはエラーチェックを抜き、まっすぐに見えます.はい、
methode=services[msg.namespace][msg.sevice][msg.method]だけです.
ここのmsg属性は以下の通りです.
namespace:「user」
service:「service」method:「echo」
見ましたよね.上の第一部を登録する時に作った木の形の構造です.
clientが呼び出した時に書いた不一致があると、上記のコードの中でエラー検出部分が淘汰されます.
OK、終了:
まとめ:
第一歩:Serverはツリー型の対応関係を構築する.
そして、clientから渡され、解析されたJSONに基づいてツリー構造に対応する関数を検索して呼び出します.
===========以下にクリエートを見て、