我是nodejs的新手,我想要的是从数据库和计算中读取数据。为了加快速度,我使用了nodejs集群模块。
有两个全局变量:pairMap和nameSet,我在主进程中将作业分配给worker,并且他们做了一些计算工作(修改map和set,就像map-reduce一样)
然而,似乎对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: name1@group.com||name2@group.com
* 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 :(得分:1)
在Node.js群集中,内存中的对象不在master和worker之间共享。
pairMap
和nameSet
分别存在于主人和每个工人中。当一个worker修改这些对象时,它们会在同一个worker(进程)中发生变化,而在master和其他worker中保持不变。
为了使您的想法有效,您需要在主进程内部维护单个pairMap
和单个nameSet
,将包含您需要的任何数据的消息发送给工作者,并使用以下内容更新这些对象收到的数据。
请注意,您不能将任何对象作为消息从worker传递到master。如果您需要一些复杂的数据,则需要发送普通的javascript对象(键值对)。例如,如果您需要将Map
实例从worker发送到master,请参阅从here获取的以下函数:
// 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)))