简体   繁体   中英

Node.js cluster error

Hello i am very new to node.js and javascript, i am trying to create a culster.js with the nodejs cluster module, at the end of my if statement i am calling server.js to start the app.

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
});

I get an error

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
      ^

Any ideas why ?

EADDRINUSE means that the port number which listen() tries to bind the server to is already in use.

You need to verify if the port is already taken on your system. To do that:

  • On linux: sudo netstat -nltp | grep (port) sudo netstat -nltp | grep (port) in your case is port 8181.
  • On OSX: sudo lsof -i -P | grep (port) sudo lsof -i -P | grep (port)

If you have a result, you need to kill the process ( kill <pid> ).

You should check if pm2 list returns 0 process. In addition, when you do a pm2 stopAll , the socket is not released. Don't forget to do a pm2 kill to be sure the daemon is killed.

$ pm2 kill
Daemon killed

Verifying for Windows:

C:\> netstat -a -b
  • a Displays all connections and listening ports.

  • b Displays the executable involved in creating each connection or listening port. In some cases well-known executables host multiple independent components, and in these cases the sequence of components involved in creating the connection or listening port is displayed. In this case the executable name is in [] at the bottom, on top is the component it called, and so forth until TCP/IP was reached. Note that this option can be time-consuming and will fail unless you have sufficient permissions.

  • n Displays addresses and port numbers in numerical form.

  • o Displays the owning process ID associated with each connection.

EXAMPLES to kill in windows command line:

If you know the name of a process to kill, for example notepad.exe, use the following command from a command prompt to end it:

taskkill /IM notepad.exe

To kill a single instance of a process, specify its process id (PID). For example , if the desired process has a PID of 827, use the following command to kill it:

taskkill /PID 827
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();
    });
  },
});

I had to add "throng" package https://www.npmjs.com/package/throng And follow the latest rules from http://eslint.org/docs/rules/

It works for me now

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM