Skip to content

Multiple connections being made/dropped using polling (express)  #3

@josefpohl

Description

@josefpohl

Hi there,
For starters, I am using Socket.io 2.1.1 (old, I know but it worked with React-Native).
I have a server that I am not sure is effectively displaying sticky behavior when polling is turned on. Here is a log entry from a single client:
process: 6680, 2021-06-01T15:48:02.941Z, socketManager, io.sockets.on(connect), Will broadcast HELLO JfLCgyTZmvMcpMgzAAFZ process: 6674, 2021-06-01T15:48:05.127Z, socketManager, io.sockets.on(connect), Will broadcast HELLO MCAoSsuLNuiGe2o3AAED process: 6680, 2021-06-01T15:48:06.989Z, socketManager, io.sockets.on(connect), Will broadcast HELLO LzxAW4_1Fhk3D4cdAAFa

The system seems to, on the initial connect seem to jump between different instances of the server (in this case the server running on process 6680 and 6674). My fear is that I do not have my server master/worker set up properly. So this is more of a question than an issue. I am using cluster and express to server dynamic and static routes. I do have a Redis client on the back end but that is receiving events properly. Here is the relevant parts of my server setup:

const express = require('express');
const app = express();
const cluster = require('cluster');
...
const { setupMaster, setupWorker } = require('@socket.io/sticky');
...
if (cluster.isMaster) {
  console.log(Master is started with process ID ${process.pid});

  const serverhttp =
    process.env.NODE_ENV === 'production'
      ? https.createServer(options, app)
      : http.Server(app);

  redisCache.setRedisUsers([]);
  setupMaster(serverhttp, {
    loadBalancingMethod: 'least-connection', // either "random", "round-robin" or "least-connection"
  });
 for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker) => {
    console.log(`Worker died on process ID ${worker.process.pid}`);
    cluster.fork();
  });
} else {
console.log(`Worker started at process ID ${process.pid}`);
  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(bodyParser.json());

  const serverhttp =
    process.env.NODE_ENV === 'production'
      ? https.createServer(options, app)
      : http.Server(app);

/* app.use routes, cors, static routes; db connection initialization */

const io = socketManager(serverhttp, redisCache); // initialize socket
  setupWorker(io);
  serverhttp.listen(port, () => {
    console.log(`Starting server on ${port}`);
  });
  serverhttp.keepAliveTimeout = 65 * 1000;
  serverhttp.headersTimeout = 66 * 1000;

}

socketManager here encapsulates the socket connection creation and all of the events tied to it. (redisCache is simply a user management cache.

The module simply exports the socket configuration code:

module.exports = function (serverhttp, redisClient) {
  const config = {
    pingTimeout: 60000,
    pingInterval: 25000,
    transports: ['polling','websocket'], 
  };
 
  const io = socketio.listen(serverhttp, config);
//Redis Adapter
  io.adapter(
    redisAdapter({
      host: REDIS_HOST,
      port: REDIS_PORT,
    })
  );

//Support functions....


 io.sockets.on('connection', function (client) {
    logIt('io.sockets.on(connect)', `Will broadcast HELLO ${client.id}`);
    io.emit('HELLO', `from io.emit -- ${client.id}`);
    client.broadcast.emit('HELLO', client.id);

    client.on(USER_CONNECTED, async (user) => {
      logIt('client.on(USER_CONNECTED)', ` ${user.name} ${client.id}`);
      user.socketId = client.id;
   
      const redisContent= await redisClient.addRedisUser({
        name: user.name,
        id: user.id,
        socketId: client.id,
      });
     io.emit(USER_CONNECTED, user); // broadcast to other clients
     });
     ... 
   //other events
  });
return io; //End of module exports function

The two things that I am wondering about in particular:

  1. In the example code the MASTER is the one listening, but I could not get the static routes under that scenario. I received a web error Cannot GET /. When I shift the app.use content to be configured with the master the page comes up but I never see the socket connections being made and the DB connection times out even though it is initialized. (The "Hello" log from above are never issued.) The one thing missing from the socket.io site example is express.
  2. The second item is that I initiate all the socket.on events prior to doing the setup worker.

Is this a case of a mis-configuration on sequencing? I s there some way to shift my master/worker configuration around such that it is using the sticky functionality and uses express but can also get the worker instances to respond on a client connection?
Is my express/https server/socket io implementation misconfigured in some way? Is there a way to get express/https to listen at both the master and the worker level. It would seem to me that while I am connecting through the master it is not being passed to a worker.
Thanks Joe

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions