2017-05-04 118 views
1

你好,我是非常新的node.js和JavaScript,我想创建一个culster.js与nodejs集群模块,在我的if语句结束时,我打电话server.js启动应用程序。Node.js集群错误

cluster.js

const cluster = require('cluster'); 
const cpuCount = require('os').cpus().length; 
const startServer = require('./server'); 

if (cluster.isMaster) { 
    for (let i = 0; i < cpuCount; i += 1) { 
    cluster.fork(); 
    } 
    cluster.on('exit',() => { 
    cluster.fork(); 
    }); 
} else { 
    return startServer; 
} 

server.js

const fs = require('fs'); 
const path = require('path'); 

const express = require('express'); 
const auth = require('http-auth'); 
const { 
    createBundleRenderer, 
} = require('vue-server-renderer'); 

const bundle = fs.readFileSync('dist/server.js', 'utf-8'); 
const renderer = createBundleRenderer(bundle); 

function parseIndexHtml() { 
    const [ 
    entire, 
    htmlOpen, 
    htmlOpenTailAndHead, 
    headCloseAndBodyOpen, 
    bodyOpenTailAndContentBeforeApp, 
    contentAfterAppAndHtmlClose, 
    ] = fs.readFileSync('index.html', 'utf8').match(/^([\s\S]+?<html)([\s\S]+?)(<\/head>[\s\S]*?<body)([\s\S]+?)<div id="?app"?><\/div>([\s\S]+)$/); 

    return { 
    entire, 
    htmlOpen, 
    htmlOpenTailAndHead, 
    headCloseAndBodyOpen, 
    bodyOpenTailAndContentBeforeApp, 
    contentAfterAppAndHtmlClose, 
    }; 
} 

const indexHtml = parseIndexHtml(); 
const app = express(); 

const basicAuth = auth.basic({ 
    realm: 'Jobportal', 
}, (username, password, callback) => { 
    callback(username === 'x' && password === 'x'); 
}); 

app.get('/ping', (request, response) => { 
    response.status(200).end(); 
}); 

app.use(auth.connect(basicAuth)); 

// serve pure static assets 
app.use('/public', express.static(path.resolve('./public'))); 
app.use('/dist', express.static(path.resolve('./dist'))); 

app.get('*', (request, response) => { 
    const context = { 
    url: request.url, 
    }; 

    renderer.renderToString(context, (error, html) => { 
    if (error) { 
     if (error.code === '404') { 
     response.status(404).end(indexHtml.entire); 
     } else { 
     response.status(500).end(indexHtml.entire); 
     console.error(`Error during render: ${request.url}`); // eslint-disable-line 
     console.error(error); // eslint-disable-line 
     } 
     return; 
    } 

    const { 
     title, 
     htmlAttrs, 
     bodyAttrs, 
     link, 
     style, 
     script, 
     noscript, 
     meta, 
    } = context.meta.inject(); 

    response.write(
     `${indexHtml.htmlOpen} data-vue-meta-server-rendered ${htmlAttrs.text()} ${indexHtml.htmlOpenTailAndHead} 
     ${meta.text()} 
     ${title.text()} 
     ${link.text()} 
     ${style.text()} 
     ${script.text()} 
     <script> 
     window.__INITIAL_STATE__ = ${JSON.stringify(context.initialState)} 
     </script> 
     ${noscript.text()} 
     ${indexHtml.headCloseAndBodyOpen} ${bodyAttrs.text()} ${indexHtml.bodyOpenTailAndContentBeforeApp} 
     ${html} 
     <script src="/dist/client.js"></script> 
     ${indexHtml.contentAfterAppAndHtmlClose}` 
    ); 

    response.end(); 
    }); 
}); 

const port = 8181; 

// start server 
app.listen(port,() => { 
    console.log(`server started at port ${port}`); // eslint-disable-line 
}); 

我得到一个错误

server started at port 8181 
events.js:163 
     throw er; // Unhandled 'error' event 
    ^

Error: bind EADDRINUSE null:8181 
    at Object.exports._errnoException (util.js:1050:11) 
    at exports._exceptionWithHostPort (util.js:1073:20) 
    at listenOnMasterHandle (net.js:1336:16) 
    at rr (internal/cluster/child.js:111:12) 
    at Worker.send (internal/cluster/child.js:78:7) 
    at process.onInternalMessage (internal/cluster/utils.js:42:8) 
    at emitTwo (events.js:111:20) 
    at process.emit (events.js:194:7) 
    at process.nextTick (internal/child_process.js:766:12) 
    at _combinedTickCallback (internal/process/next_tick.js:73:7) 
events.js:163 
     throw er; // Unhandled 'error' event 
    ^

任何想法,为什么?

+0

你应该发布你的'startServer'代码。查看错误,您可能需要明确设置服务器的IP地址或主机名。 –

+0

@ Sebastian-LaurenţiuPlesciuc我已添加代码。谢谢 – Momo

+0

您需要验证端口是否已经在您的系统上使用。 –

回答

1
const throng = require('throng'); 

throng({ 
    master:() => { 
    console.log('Started master'); 
    }, 
    start: (id) => { 
    console.log(`Started worker ${id}`); 
    require('./server'); 

    process.on('SIGTERM',() => { 
     console.log(`Worker ${id} exiting...`); 
     process.exit(); 
    }); 
    }, 
}); 

我不得不添加“大群”包https://www.npmjs.com/package/throng 并按照最新的规则从http://eslint.org/docs/rules/

它现在适用于我

+0

很高兴你能解决问题:) +1 –

1

EADDRINUSE表示listen()试图绑定服务器的端口号已被使用。

您需要验证端口是否已经在您的系统上使用。要做到这一点:

  • 在Linux上:sudo netstat -nltp | grep (port)你的情况是8181端口
  • 在OSX:sudo lsof -i -P | grep (port)

如果你有一个结果,你需要kill过程(kill <pid>)。

您应该检查pm2 list是否返回0进程。另外,当您执行pm2 stopAll时,套接字未被释放。不要忘记执行pm2 kill以确保守护进程被终止。

$ pm2 kill 
Daemon killed 

验证的Windows:

C:\> netstat -a -b 
  • a显示所有连接和侦听端口。

  • b显示创建每个连接或侦听端口时涉及的可执行文件。在某些情况下,众所周知的可执行文件会托管多个独立组件,并且在这些情况下,会显示创建连接或侦听端口时所涉及的组件序列。在这种情况下,可执行文件的名称位于底部的[]中,最上面是它所调用的组件,等到TCP/IP达到。请注意,此选项可能非常耗时,并且会失败,除非您拥有足够的权限。

  • n以数字形式显示地址和端口号。

  • o显示与每个连接关联的拥有进程ID。

例子来杀死在Windows命令行:

如果你知道一个进程杀掉,为example记事本的名字。exe,请从命令提示符使用以下命令结束它:

taskkill /IM notepad.exe 

要杀死一个进程的单个实例,请指定其进程ID(PID)。对于example,如果需要的过程有827 PID,使用下面的命令来杀死它:

taskkill /PID 827 
+0

感谢您的帮助,我已经尝试过了,港口是免费使用,我得不到答案。 – Momo

+0

@Momo笔记'控制台中的服务器端口8181'开始,意味着它已经连接,但之后你尝试连接另一个时间 –

+0

正确!我想这与我的if语句有关! – Momo