首页 > 解决方案 > 将带有集群模块项目的node.js部署到heroku时绑定EADDRINUSE null错误

问题描述

我有一个在前端使用 Node 集群模块、Express.js、Socket.io 和 React 构建的 Messenger 应用程序。我一直在尝试将我的应用程序部署到 heroku,但是当我检查 heroku 控制台时出现 EADDRINUSE null 错误,并且我还看到该应用程序在 heroku 日志中以代码 H10 崩溃。我意识到工作线程可能正在连接到同一个端口,因此出现了错误。我尝试了许多不同的方法,但我无法解决问题。

这是我的 server.js 代码和集群模块代码:

require('dotenv').config();
const express = require('express'),
    mongoose = require('mongoose'),
    socketio = require('socket.io'),
    helmet = require('helmet'),
    hpp = require('hpp'),
    path = require('path'),
    net = require('net'),
    cluster = require('cluster');

const num_processes = require('os').cpus().length;
const io_redis = require('socket.io-redis');
const farmhash = require('farmhash');
const port = process.env.PORT || 8080;

const User = require('./models/User');
const socketMain = require('./sockets/socketMain');

if (cluster.isMaster) {
    let workers = [];

    // Helper function for spawning worker at index 'i'.
    let spawn = function(i) {
        workers[i] = cluster.fork();

        // Optional: Restart worker on exit
        workers[i].on('exit', function(code, signal) {
            // console.log('respawning worker', i);
            spawn(i);
        });
    };

    // Spawn workers.
    for (var i = 0; i < num_processes; i++) {
        spawn(i);
    }

    const worker_index = function(ip, len) {
        return farmhash.fingerprint32(ip) % len; // Farmhash is the fastest and works with IPv6, too
    };

    const server = net.createServer({ pauseOnConnect: true }, (connection) =>{
        let worker = workers[worker_index(connection.remoteAddress, num_processes)];
        worker.send('sticky-session:connection', connection);
    });
    server.listen(port, process.env.IP, () => {
        console.log(`Master listening on port ${port}`);
    });
} else {
    let app = express();
    app.use(express.json({limit: '50mb'}));
    app.use(helmet());
    app.use(hpp());
    
    // Mongo Connection
    mongoose.connect(process.env.DB_URL, {
        useNewUrlParser: true,
        useCreateIndex: true,
        useUnifiedTopology: true,
        useFindAndModify: false
    })
    .then(() => console.log('Connected to dB!'))
    .catch(e => console.log(e));

    // Don't expose our internal server to the outside world.
    // Serve static assets if in production
    if(process.env.NODE_ENV === 'production') {
        // Set static folder
        app.use(express.static(path.join(__dirname, 'client', 'build')));

        app.get('*', (req, res) => {
            res.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
        });
    }
    const server = app.listen(port, () => {
          console.log("Worker listening..."); 
    });   
    const io = socketio(server, {
        cors: {
            origin: "http://localhost:3000",
            methods: ["GET", "POST"],
            allowedHeaders: ["my-custom-header"],
            credentials: true
          }
    });

    io.adapter(io_redis({ host: 'localhost', port: 6379 }));

    io.on('connection', async (socket) => {
        const userId = socket.handshake.query.userId;
        //Socket code here
    });
    
    // Use API routes
    const userRoutes = require('./routes/api/user'),
        authRoutes = require('./routes/api/auth'),
        messengerRoutes = require('./routes/api/messenger')(io);
    app.use('/api/user', userRoutes);
    app.use('/api/auth', authRoutes);
    app.use('/messenger', messengerRoutes);

    // Listen to messages sent from the master. Ignore everything else.
    process.on('message', function(message, connection) {
        if (message !== 'sticky-session:connection') {
            return;
        }

        // Emulate a connection event on the server by emitting the
        // event with the connection the master sent us.
        server.emit('connection', connection);

        connection.resume();
    });
}

请帮我解决问题。

标签: node.jsreactjsexpresssocket.ionode-cluster

解决方案


推荐阅读