node.js中RPC(遠程過程調用)的實現原理介紹
來源:易賢網 閱讀:971 次 日期:2014-12-19 14:18:24
溫馨提示:易賢網小編為您整理了“node.js中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.整個過程完成,詳見源碼:

幾個注意的點:

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端調用時能在本地找到這個函數??梢詤⒖糳node的實現。

更多信息請查看IT技術專欄

更多信息請查看腳本欄目
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!

2026國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
云南網警備案專用圖標
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網
云南網警報警專用圖標
未满十八18勿进黄网站免费看