问题描述
我的应用是在内部使用原始nodejs集群代码的应用程序,并由node ./dist/main.js运行 但是当我使用pm2 start ./dist/main.js
时会出错//my code
import cluster from 'cluster'
import http from 'http'
if(cluster.isMaster){
(async()=>{
const master = await (await import('./master'))
async function onMsg(pid:number,type?:string,num?:number,data?:{db:any,apiName:any,args:Array<any>}){
console.log(`master receiving message from cluster ${pid}`)
try{
let result = await master.publishMission(type,data)
// console.log(`${type} finish mission and send back to koa cluster ${pid}`)
cluster.workers[pid].send({num:num,status:true,data:result})
}catch(err){
cluster.workers[pid].send({num:num,err})
}
}
//cluster nums
for(let i=0;i<1;i++){
cluster.fork()
}
cluster.on('message',(worker,msg)=>{
onMsg(worker.id,...msg)
})
cluster.on('exit',code,signal) => {
console.log('worker %d died (%s). restarting...',worker.process.pid,signal || code);
cluster.fork();
});
})()
}else{
(async()=>{
const app = await (await import('./app')).app
try{
http.createServer(app).listen(5000)`enter code here`
console.log("fork new koa server",process.pid)
}catch(err){
console.log(err)
}
})()
}
//错误日志 TypeError:发现不可调用的@@ iterator 在EventEmitter。 (C:\ Users \ yany \ project \ Jmrh_Warehouse \ src \ main.ts:22:13) 在EventEmitter.emit(events.js:315:20) 在工人。 (内部/集群/master.js:174:13) 在Worker.emit(events.js:315:20) 在ChildProcess。 (内部/集群/worker.js:32:12) 在ChildProcess.emit(events.js:315:20) 发出时(internal / child_process.js:903:12) 在processticksAndRejections(内部/进程/task_queues.js:81:21) TypeError:发现不可调用的@@ iterator 在EventEmitter。 (C:\ Users \ yany \ project \ Jmrh_Warehouse \ src \ main.ts:22:13) 在EventEmitter.emit(events.js:315:20) 在工人。 (内部/集群/master.js:174:13) 在Worker.emit(events.js:315:20) 在ChildProcess。 (内部/集群/worker.js:32:12) 在ChildProcess.emit(events.js:315:20) 发出时(internal / child_process.js:903:12) 在processticksAndRejections(internal / process / task_queues.js:81:21)
解决方法
pm2在内部实现集群。
因此,端口共享可能存在问题。
其中:dist/main.js
是
(async()=>{
const app = await (await import('./app')).app
try{
http.createServer(app).listen(5000)`enter code here`
console.log("fork new koa server",process.pid)
}catch(err){
console.log(err)
}
})()
pm2 start dist/main.js -i max
可能有效。 -i
以集群模式启动pm2。
https://pm2.keymetrics.io/docs/usage/cluster-mode/
,通过使用pm2 start dist/main.js -i 1
,此错误结束
因此,当使用pm2 fork时,可能会禁用内部的集群消息转换
但是出现了新问题
const master = await (await import('./master'))
此代码无效
当我使用节点dist / main.js但不能在pm2中工作时很好
import * as cl from 'child_process'
import {EventEmitter} from 'events'
const event = new EventEmitter()
const autoReboot = false
var count = 0
console.log("fine")
interface masterStore{
[typeOfChild:string]:{
childGroup?:Array<cl.ChildProcess>,workIndex:number,maxNum?:number,}
}
var master:masterStore={}
//child process of database
master['mongodb'] = {
childGroup:[],workIndex:0,maxNum:1
}
for(let i =0;i<master['mongodb'].maxNum;i++){
forkNewDB()
}
function forkNewDB(){
var db = cl.fork(`${__dirname}/data/index.js`)
master['mongodb'].childGroup.push(db)
db.on('exit',(signal)=>{
console.log(`db process ${db.pid} exit with code ${signal}`)
let index = master['mongodb'].childGroup.findIndex(el=>el.pid==db.pid)
master['mongodb'].childGroup.splice(index,1)
if(autoReboot){
forkNewDB()
}
})
db.on('message',async (msg:{des:string,type:string,ev:string,result?:any,err?:any,data?:any,num?:any})=>{
if(msg.des=="res"){
event.emit(msg.ev,{msg})
}else{
try{
let result = await publishMission(msg.type,msg.data)
db.send({des:"res",num:msg.num,status:true,data:result})
}catch(err){
db.send({des:"res",err})
}
}
})
}
//child process of rabbitmq
master['rabbitmq'] = {
childGroup:[],maxNum:1
}
function forkNewMQ(){
var mq = cl.fork(`${__dirname}/mq/index.js`)
master['rabbitmq'].childGroup.push(mq)
mq.on('exit',(signal)=>{
console.log(`mq process ${mq.pid} exit with code ${signal}`)
master['rabbitmq'].childGroup.splice(0,1)
if(autoReboot){
forkNewMQ()
}
})
mq.on('message',msg.data)
mq.send({des:"res",data:result})
}catch(err){
mq.send({des:"res",err})
}
}
})
}
forkNewMQ()
//child process of redis
master['redis'] = {
childGroup:[],maxNum:1
}
function forkNewRedis(){
var redis = cl.fork(`${__dirname}/redis/index.js`)
master['redis'].childGroup.push(redis)
redis.on('exit',(signal)=>{
console.log(`redis process ${redis.pid} exit with code ${signal}`)
let index = master['redis'].childGroup.findIndex(el=>el.pid==redis.pid)
master['redis'].childGroup.splice(index,1)
if(autoReboot){
forkNewRedis()
}
})
redis.on('message',msg.data)
redis.send({des:"res",data:result})
}catch(err){
redis.send({des:"res",err})
}
}
})
}
forkNewRedis()
//init message publish
function publishMission(type?:string,data?:{db:any,apiName:any,args:Array<any>}):Promise<any>{
return new Promise(async (res,rej)=>{
try{
let tmp = master[type].workIndex
master[type].workIndex++
master[type].workIndex=master[type].workIndex%master[type].maxNum
let ev = count+""
// console.log(`master publish mission to ${type}`)
master[type].childGroup[tmp].send({data,ev,des:"req"})
count++
event.once(ev,(result)=>{
if(!result.msg.err){
res(result.msg.result)
}else{
rej(result.msg.err)
}
event.removeListener(ev,()=>{})
})
}catch(err){
rej(err)
}
})
}
export{publishMission}
节点dist /主日志应为
fine
child process 10116 rabbitmq is ready
fork new koa server 15948
child process 10008 create DB thread 1