ホームページ  >  記事  >  ウェブフロントエンド  >  node.js_node.js における RPC (リモート プロシージャ コール) の実装原理の紹介

node.js_node.js における RPC (リモート プロシージャ コール) の実装原理の紹介

WBOY
WBOYオリジナル
2016-05-16 16:29:002588ブラウズ

私はちょうど RPC (リモート プロシージャ コール) について触れました。これは、リモート マシン上のプログラムをローカルで呼び出すことができる方法であり、RPC の原理を学ぶのに非常に適した単純な Nodejs 実装を見ました。 🎜>nodejs light_rpc

使用例:

コードをコピーします コードは次のとおりです:
//サーバー
var light_rpc = require('./index.js');
var port = 5556;
var rpc = new light_rpc({
結合: function(a, b, callback){
callback(a b);
}、
乗算: function(t, cb){
cb(t*2);
}
}).listen(ポート);

サンプルクライアント:

コードをコピーします コードは次のとおりです:
//クライアント
rpc.connect(5556, 'localhost', function(remote, conn){
Remote.combine(1, 2, function(res){
If(res != 3){
console.log('エラー', レス);
}
});
});

プロセス全体について簡単に説明します:

1. サーバーはプログラムを開始し、ポートをリッスンし、クライアントによって呼び出される関数 (上記の例では結合や乗算など) を実装し、それらをオブジェクトに保存します。

2. クライアントはプログラムを開始し、サーバーに接続し、接続の完了後に description コマンドを送信して、呼び出しに提供できる関数名を返すようにサーバーに要求します。

コードをコピーします コードは次のとおりです:
connection.on('接続', function(){
connection.write(command(descrCmd));
});

3. サーバーは、describe コマンドを受信し、その呼び出し可能な関数名をラップして送信します (「結合」、「乗算」)

4. クライアントは、サーバーから送信された関数名を受信し、それを独自のオブジェクトに登録し、各関数名のメソッドをラップします。これにより、これらの関数をローカルで呼び出すときに、実際にサーバーにリクエストが送信されます。

コードをコピーします コードは次のとおりです:
for(cmd.data の var p){
RemoteObj[p] = getRemoteCallFunction(p, self.callbacks, connection);
//getRemoteCallFunction の実装を以下に示します
}

5. クライアントはサーバー側関数を呼び出します:

1) callbackId という着信コールバック関数の一意の ID を生成し、クライアントのオブジェクトに記録します。

2) 次のデータをパッケージ化してサーバーに送信します: 呼び出し関数名、JSON シリアル化パラメーター リスト、callbackId

コードをコピーします コードは次のとおりです:
function getRemoteCallFunction(cmdName, コールバック, 接続){
return function(){
var id = uuid.generate();
If(引数の種類[引数.長さ-1] == '関数'){
コールバック[id] = 引数[arguments.length-1];
}
var args = parseArgumentsToArray.call(this, argument);
var newCmd = command(cmdName, {id: id, args: args});
Connection.write(newCmd);
}
}

6. サーバーは上記の情報を受信し、データを解析し、パラメーター リストを逆シリアル化して、関数名とパラメーターに従って関数を呼び出します。

コードをコピーします コードは次のとおりです:
var args = cmd.data.args;
args.push(getSendCommandBackFunction(c, cmd.data.id));
self.wrapper[cmd.command].apply({}, args);

7. 関数が完了したら、結果をシリアル化し、以前に受信した callbackId とともにクライアントに送り返します。

コードをコピー コードは次のとおりです:

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

8. クライアントは関数の演算結果と callbackId を受け取り、callbackId に基づいてコールバック関数を取り出し、演算結果をコールバック関数に渡して実行します。

9. プロセス全体が完了しました。詳細についてはソース コードを参照してください: https://github.com/romulka/nodejs-light_rpc

いくつかの注意点:

1. クライアントとサーバーは処理中ずっと接続されたままになります。HTTP プロトコルとは異なり、送信と受信後に接続が切断されるため、接続の切断によってデータ送信の完了を判断することはできません。データ受信の完了を判断するために、クライアントとサーバーによって送信されるデータは、データ パケットの長さとデータの前にデリミタを追加するという単純なプロトコルに従います。たとえば、デリミタは n: [パケット長です。 データ]を選択することで、データを受信後、まずデータパケットの長さを取り出し、累積して受信したデータパケットがその長さ以上であるかどうかを継続的に判定し、それ以上であれば、1回のデータ送信が完了することができます。データの解析と抽出を開始します。

2. この RPC は、パラメーター内の関数の型を考慮しないため、単純です。たとえば、パラメーターがオブジェクトであり、このオブジェクトの下に関数メンバーがある場合、その関数は JSON シリアル化中に無視されます。のサーバー側では関数を実行できません。

この問題を解決するには、複雑な処理が必要です:

1. リモート エンドに送信される各パラメーターを詳細に調べ、関数メンバーを抽出し、この関数の一意の ID を生成し、それをローカル オブジェクトに配置し、この関数メンバーをこの ID 文字列で置き換えて識別します。 member は実際には関数です。このようにして、オブジェクトをシリアル化して送信できます。
2. サーバーは、パラメーター オブジェクト内の関数を使用する場合、これがクライアントによって処理され、ID を持つ関数であると判断し、その ID をクライアントに送り返します。同じメソッドで独自のコールバック関数を設定し、クライアントに ID を渡し、クライアントからのコールバックを待ちます。
3. クライアントは関数 ID を受け取り、関数エンティティを見つけて呼び出し、完了後にサーバーから指定されたコールバック ID に従ってサーバーに送り返します
4. サーバーは結果を受信し、コールバック関数を見つけて実行を継続し、完了します。

関数の記録方法は、他の方法でも完了できます。一般的な考え方は、関数をシリアル化できるものに置き換え、リモート側で呼び出されたときに関数をローカルで見つけられるようにすることです。 dnode の実装を参照できます。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。