node中怎么利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。
目前創(chuàng)新互聯(lián)已為數(shù)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、網(wǎng)站托管維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、太和網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
##IPC的基本用法:
// worker進(jìn)程 發(fā)送消息 process.send(‘讀取共享內(nèi)存'); // master進(jìn)程 接收消息 -> 處理 -> 發(fā)送回信 cluster.on('online', function (worker) { // 有worker進(jìn)程建立,即開始監(jiān)聽message事件 worker.on(‘message', function(data) { // 處理來自worker的請(qǐng)求 // 回傳結(jié)果 worker.send(‘result') }); });
在Node.js中,通過send和on(‘message', callback)實(shí)現(xiàn)的IPC通信有幾個(gè)特點(diǎn)。首先,master和worker之間可以互相通信,而各個(gè)worker之間不能直接通信,但是worker之間可以通過master轉(zhuǎn)發(fā)實(shí)現(xiàn)間接通信。另外,通過send方法傳遞的數(shù)據(jù),會(huì)先被JSON.stringify處理后再傳遞,接收后會(huì)再用JSON.parse解析。所以Buffer對(duì)象傳遞后會(huì)變成數(shù)組,而function則無法直接傳遞。反過來說,就是可以直接傳遞除了buffer和function之外的所有數(shù)據(jù)類型(已經(jīng)很強(qiáng)大了,而且buffer和function也可以用變通的方法實(shí)現(xiàn)傳遞)。
基于以上特點(diǎn),我們可以設(shè)計(jì)一個(gè)通過IPC來共享內(nèi)存的方案:
1、worker進(jìn)程作為共享內(nèi)存的使用者,并不直接操作共享內(nèi)存,而是通過send方法通知master進(jìn)程進(jìn)行寫入(set)或者讀取(get)操作。
2、master進(jìn)程初始化一個(gè)Object對(duì)象作為共享內(nèi)存,并根據(jù)worker發(fā)來的message,對(duì)Object的鍵值進(jìn)行讀寫。
3、由于要使用跨進(jìn)程通信,所以worker發(fā)起的set和get都是異步操作,master根據(jù)請(qǐng)求進(jìn)行實(shí)際讀寫操作,然后將結(jié)果返回給worker(即把結(jié)果數(shù)據(jù)send給worker)。
##數(shù)據(jù)格式
為了實(shí)現(xiàn)進(jìn)程間異步的讀寫功能,需要對(duì)通信數(shù)據(jù)的格式做一點(diǎn)規(guī)范。
首先是worker的請(qǐng)求數(shù)據(jù):
requestMessage = { isSharedMemoryMessage: true, // 表示這是一次共享內(nèi)存的操作通信 method: ‘set', // or ‘get' 操作的方法 id: cluster.worker.id, // 發(fā)起操作的進(jìn)程(在一些特殊場(chǎng)景下,用于保證master可以回信) uuid: uuid, // 此次操作的(用于注冊(cè)/調(diào)用回調(diào)函數(shù)) key: key, // 要操作的鍵 value: value // 鍵對(duì)應(yīng)的值(寫入) }
master在接到數(shù)據(jù)后,會(huì)根據(jù)method執(zhí)行相應(yīng)操作,然后根據(jù)requestMessage.id將結(jié)果數(shù)據(jù)發(fā)給對(duì)應(yīng)的worker,數(shù)據(jù)格式如下:
responseMessage = { isSharedMemoryMessage: true, // 標(biāo)記這是一次共享內(nèi)存通信 uuid: requestMessage.uuid, // 此次操作的唯一標(biāo)示 value: value // 返回值。get操作為key對(duì)應(yīng)的值,set操作為成功或失敗 }
規(guī)范數(shù)據(jù)格式的意義在于,master在接收到請(qǐng)求后,能夠?qū)⑻幚斫Y(jié)果發(fā)送給對(duì)應(yīng)的worker,而worker在接到回傳的結(jié)果后,能夠調(diào)用此次通信對(duì)應(yīng)的callback,從而實(shí)現(xiàn)協(xié)同。
規(guī)范數(shù)據(jù)格式后,接下來要做的就是設(shè)計(jì)兩套代碼,分別用于master進(jìn)程和worker進(jìn)程,監(jiān)聽通信并處理通信數(shù)據(jù),實(shí)現(xiàn)共享內(nèi)存的功能。
##User類
User類的實(shí)例在worker進(jìn)程中工作,負(fù)責(zé)發(fā)送操作共享內(nèi)存的請(qǐng)求,并監(jiān)聽master的回信。
var User = function() { var self = this; self.__uuid__ = 0; // 緩存回調(diào)函數(shù) self.__getCallbacks__ = {}; // 接收每次操作請(qǐng)求的回信 process.on('message', function(data) { if (!data.isSharedMemoryMessage) return; // 通過uuid找到相應(yīng)的回調(diào)函數(shù) var cb = self.__getCallbacks__[data.uuid]; if (cb && typeof cb == 'function') { cb(data.value) } // 卸載回調(diào)函數(shù) self.__getCallbacks__[data.uuid] = undefined; }); }; // 處理操作 User.prototype.handle = function(method, key, value, callback) { var self = this; var uuid = self.__uuid__++; process.send({ isSharedMemoryMessage: true, method: method, id: cluster.worker.id, uuid: uuid, key: key, value: value }); // 注冊(cè)回調(diào)函數(shù) self.__getCallbacks__[uuid] = callback; }; User.prototype.set = function(key, value, callback) { this.handle('set', key, value, callback); }; User.prototype.get = function(key, callback) { this.handle('get', key, null, callback); };
##Manager類
Manager類的實(shí)例在master進(jìn)程中工作,用于初始化一個(gè)Object作為共享內(nèi)存,并根據(jù)User實(shí)例的請(qǐng)求,在共享內(nèi)存中增加鍵值對(duì),或者讀取鍵值,然后將結(jié)果發(fā)送回去。
var Manager = function() { var self = this; // 初始化共享內(nèi)存 self.__sharedMemory__ = {}; // 監(jiān)聽并處理來自worker的請(qǐng)求 cluster.on('online', function(worker) { worker.on('message', function(data) { // isSharedMemoryMessage是操作共享內(nèi)存的通信標(biāo)記 if (!data.isSharedMemoryMessage) return; self.handle(data); }); }); }; Manager.prototype.handle = function(data) { var self = this; var value = this[data.method](data); var msg = { // 標(biāo)記這是一次共享內(nèi)存通信 isSharedMemoryMessage: true, // 此次操作的唯一標(biāo)示 uuid: data.uuid, // 返回值 value: value }; cluster.workers[data.id].send(msg); }; // set操作返回ok表示成功 Manager.prototype.set = function(data) { this.__sharedMemory__[data.key] = data.value; return 'OK'; }; // get操作返回key對(duì)應(yīng)的值 Manager.prototype.get = function(data) { return this.__sharedMemory__[data.key]; };
##使用方法
if (cluster.isMaster) { // 初始化Manager的實(shí)例 var sharedMemoryManager = new Manager(); // fork第一個(gè)worker cluster.fork(); // 1秒后fork第二個(gè)worker setTimeout(function() { cluster.fork(); }, 1000); } else { // 初始化User類的實(shí)例 var sharedMemoryUser = new User(); if (cluster.worker.id == 1) { // 第一個(gè)worker向共享內(nèi)存寫入一組數(shù)據(jù),用a標(biāo)記 sharedMemoryUser.set('a', [0, 1, 2, 3]); } if (cluster.worker.id == 2) { // 第二個(gè)worker從共享內(nèi)存讀取a的值 sharedMemoryUser.get('a', function(data) { console.log(data); // => [0, 1, 2, 3] }); } }
關(guān)于node中怎么利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
網(wǎng)頁標(biāo)題:node中怎么利用進(jìn)程通信實(shí)現(xiàn)Cluster共享內(nèi)存
標(biāo)題鏈接:http://www.rwnh.cn/article38/jipppp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、靜態(tài)網(wǎng)站、標(biāo)簽優(yōu)化、全網(wǎng)營銷推廣、虛擬主機(jī)、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)