mdmb
mdmb

Reputation: 5283

SocketIO – connection issues and clustering

I have a really simple NodeJS app that I want to run on Heroku. This is how the index.js file looks like:

Server (port 3030)

const http = require('http');
const os = require('os');
const express = require('express')
const throng = require('throng'); // For cluster management
const { port, env, isProduction } = require('./config/vars');
const SocketIO = require('socket.io');


// Setting up a simple express app and wrapping it with http server
const setupServer = () => {
  const app = express();

  app.use(express.static(path.join(__dirname, '../public')));

  const server = http.createServer(app);
  return server;
};


const setupSocket = (server) => {
  const io = new SocketIO(server);
  io.on('connection', (socket) => {
    console.log(`[Socket] Connection established: ${socket.id}`);
    socket.on(msg.rooms.join, (room) => {
      socket.join(room);
      socket.to(room).emit(msg.rooms.joined);
      console.log(`[Socket] User ${socket.id} joined '${room}' room`);
    });
    socket.on('disconnect', () => {
      console.log(`[Socket] Distonnected: ${socket.id}`);
    });
  });
  return io;
};

const WORKERS = (() => {
  if (!isProduction) return 1;
  return process.env.WEB_CONCURRENCY || os.cpus().length;
})();

async function master() {
  console.log(`Preparing ${WORKERS} workers...`);
  console.log('Master started.');
}

// There should be one server instance for each worker
const start = () => {
  const server = setupServer(); // Returns and `http` server instance
  const socket = setupSocket(server);
  server.listen(port, async () => {
    Logger.info(`Server – listening on port ${port}`);
  });
  return server;
};

const instance = throng({
  workers: WORKERS,
  lifetime: Infinity,
  start,
  master,
});

module.exports = instance;

Client (port 3000)

const setupSocket = ({ room }) => {
  // Fallback if already setup
  if (window.sockets[room]) {
    return window.sockets[room];
  }
  const socket = io('http://localhost:3030');
  socket.on('connect', () => {
    console.log('[Socket] Connection established!', socket.id);
    socket.emit('room.join', room);
  });
  socket.on('room.joined', () => {
    console.log(`[Socket] Connected to ${room} room!`);
  });
  window.sockets[key] = socket;
  return socket
};

The problem – the connection is sometimes established properly but most of the time I get an error

Error during WebSocket handshake: Unexpected response code: 400

What might be the problem here? Is it because I have it on two different ports or is it because of the clusters?

I've tried removing the throng part of the code, and just calling start() method without any cluster setup, but the problem remains :(

Upvotes: 0

Views: 135

Answers (1)

William
William

Reputation: 41

why would you use http module? The server instance that you send in the socketIO constructor should be the return object of the expressInstance.listen

Something more like this:

const express= require('express')
const app = express()
const socketio = require('socket.io')

app.use(express.static(__dirname + '/public'))

const server = app.listen('4000',()=>{
   console.log('Listening to port:4000')
})
const io = socketio(server)

io.on('connect',(socket)=>{

   socket.broadcast.emit('new_user')

   socket.on('new_message',(message)=>{
      io.emit('new_message',message)
   })

})

source code: socket-io chat

Upvotes: 0

Related Questions