2017-11-19 15 views
1

私はnodejsを初めて使いました。データベースからデータを読み込み、計算することができます。これを高速化するために、nodejsクラスタモジュールを使用します。NodeJSクラスタ:マスタのワーカーからのデータを削減する方法は?

が牽引グローバル変数です:(ジャスト減らすマップのように、マップおよびセットを変更するために)pairMapと名前セットは、と私はマスター・プロセスで労働者に仕事を割り当て、そして、彼らはいくつかの計算作業を行う

しかし、pairMapとnameSetは変更されず空ではないようです。(doMasterActionのコード) (別の奇妙なことは、私はデータをコンソールにしていますが、最終的には変更されましたが、マスタープロセスでは空に戻ります)。次のように

データは、(私は主要なアイデアを抽出)である:

const Promise = require('bluebird'); 
const cluster = require('cluster'); 
const numCPUs = require('os').cpus().length; 
const fs = Promise.promisifyAll(require('fs')) 

const utils = { 
    mergeMap:(source,dest)=>{ 
     for(let [key,value] of Object.entries(source)){ 
      if(!dest.has(key)) dest.set(key,value); 
      for(let [type,arr] of Object.entries(value)){ 
       const final = new Set([...dest.get[key][type],...arr]) 
       dest.get[key][type] = final; 
      } 
     } 
    } 
} 


/** 
* key: [email protected]||[email protected] 
* value: {to: [id1,id2,id3],cc,bcc} 
* @param row 
* @param map 
* @param nameSet 
*/ 
function countLinks(res,map,nameSet) { 
    nameSet.add(res); 
    map.set(res,{ 'test': Math.floor(Math.random()*10+1)}); 
} 


class hackingTeamPrepare { 

    constructor(bulk=100000,total = 1150000){ 
     this.bulk = bulk; 
     this.count = Math.ceil(total/this.bulk); 
     const parallelArr = new Array(this.count).fill(0).map((v,i)=> i); 
     this.jobs = parallelArr.map(v=> 'key'+v); 
     this.pairMap = new Map(); 
     this.nameSet = new Set(); 

     this.bindThis(); 
    } 

    bindThis(){ 
     this.doWorkerAction = this.doWorkerAction.bind(this); 
     this.doMasterAction = this.doMasterAction.bind(this); 
    } 

    doMasterAction() { 
     const workers = [],result = {}; 
     const self = this; 
     let count = 0,timeout; 

     for(let i=0;i<numCPUs;i++){ 
      const worker = cluster.fork(); 
      workers[i] = worker; 
     } 
     cluster.on('online', (worker) => { 
      worker.send(self.jobs.shift()); 
     }); 
     cluster.on('exit', function() { 
      if(self.jobs.length===0) return; 
      console.log('A worker process died, restarting...'); 
     }); 

     cluster.on('message',function (senderWorkder,info) { 
      const { workerId,jobIndex } = info; 
      result[jobIndex] = true; 
      console.log(`----worker ${workerId} done job: ${jobIndex}----`); 

      const finish = !self.jobs.length && Object.keys(result).length===self.count; 
      if(finish){ 
       // -----------------!!here!!--------------------------** 
       console.log('-------finished-------',self.pairMap,self.nameSet); // Map {}, Set {} 
       for(let id in cluster.workers){ 
        const curWorker = cluster.workers[id]; 
        curWorker.disconnect(); 
       } 
      }else{ 
       if(!self.jobs.length) return; 
       senderWorkder.send(self.jobs.shift()); 
      } 
     }) 
    } 



    /** 
    * {[person1,person2]: {to,cc,bcc}} 
    */ 
    doWorkerAction() { 
     //Process为worker, receive from master 
     const self = this; 
     process.on('message',(sql)=>{ 
      const jobPromise = Promise.resolve(sql).then(res => { 
        countLinks(res,self.pairMap,self.nameSet); 
        const data = { 
         workerId: process.pid, 
         jobIndex: sql, 
        } 

        // send to master 
        process.send(data); 
       }).catch(err=> { 
       console.log('-----query error----',err) 
      }); 
     }) 
    } 

    readFromPG(){ 
     if(cluster.isMaster){ 
      this.doMasterAction(); 
     }else if (cluster.isWorker){ 
      this.doWorkerAction(); 
     } 
    } 

    init(){ 
     this.readFromPG(); 
    } 
} 

const test = new hackingTeamPrepare(2,10); 
test.init(); 

誰もがこれで私を助けることができますか?

私はマスタープロセスで手動でデータをマージしようとしましたが、worker.sendによって送信されたデータはその中のオブジェクトを無視しているようです。

答えて

0

Node.jsクラスターでは、メモリー内のオブジェクトはマスターとワーカー間で共有されません。

pairMapおよびnameSetは、マスタおよびすべての作業者に別々に存在します。作業者がこれらのオブジェクトを変更すると、それらは同じ作業者(プロセス)で変更され、マスタおよび他の作業者には変更されません。

pairMapと1つのnameSetをマスタプロセス内に維持し、必要なデータを含むメッセージをワーカーからマスタに送信し、受け取ったデータを使用してこれらのオブジェクトを更新する必要があります。

ワーカーからマスターにメッセージとしてオブジェクトを渡すことはできません。やや複雑なデータが必要な場合は、プレーンなjavascriptオブジェクト(キーと値のペア)を送信する必要があります。たとえば、あなたがhereから取られた以下の機能を参照してください、労働者からマスターにMapインスタンスを送信する必要がある場合:

// source - http://2ality.com/2015/08/es6-map-json.html 
function mapToJson(map) { 
    return JSON.stringify([...map]); 
} 
function jsonToMap(jsonStr) { 
    return new Map(JSON.parse(jsonStr)); 
} 

// send message using this example: 
process.send(mapToJson(pairMap)); 

// receive message: 
worker.on('message', message => console.log(jsonToMap(message))) 
+0

はい、私はいくつかの時間後にこの溶液に変更し、私はからデータを送信するときことがわかりました作業者をマスターするには、マップまたはセットタイプ(すべてが空の{}に変更されている)を含むべきではありません。理由を理解できません。 – luchen

+0

と私はWebstormでクラスタをデバッグできないようですか? – luchen

+0

私の更新された回答を見る –

関連する問題