2017-05-04 139 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