4

I'm very new to node.js (generally beginner in server issues).

I managed to run my node.js app and put it online on my virtual server (Linux 8.0).

The problem is that node.js opens a lot of TCP sockets. After some time the number of allowed sockets is exhausted and the server crashes. I currently have to manually stop and restart the node process to prevent this. The restarting resets the TCP sockets.

I need to find a solution for this issue because restarting it manually is not a long term fix, especially if the number of visitors will increase and I probably would need to restart it every 12 hours (which is just not practical).

I am probably doing something wrong in the coding but I currently have no idea what I can optimize. I'm happy that it even works. Which part of the code is creating all these TCP connection? How can I solve this?

My node file/app does the following:

  • send/emits messages to an open and/or private chat.
  • send/emits invitation for a game (type of game is not important)
  • if invite accepts invitation both 'clients' are send to the same room and game starts

nodeServer.js

var socket = require( 'socket.io' );
var express = require( 'express' );
var http = require( 'http' );

var app = express();
var server = http.createServer( app );

var io = socket.listen( server );

// handle incoming connections from clients
io.sockets.on( 'connection', function( client ) {

  // Message Emit for match invite
  client.on( 'sendmatchinvite', function( data ) {
    console.log( 'Match invite for '+data.opponent+' from '+data.sender);
    client.broadcast.emit('sendmatchinvite', { tmpmatch:data.tmpmatch, recepient: data.opponent, sender: data.sender } );
  });

  // Answer of invite 
  client.on( 'checkinviteanswer', function( data ) {
    console.log( 'Invitation '+data.answer+' from '+data.id+' in '+data.room);
    client.broadcast.to(data.room).emit('checkinviteanswer', { host:data.host } );
  });

  // Register Room
  client.on('room', function(room) {
    console.log( 'Client joined the room: '+room);
    client.join(room);
  });

  // Score Emit for online games
  client.on( 'score', function( data ) {
    console.log( 'New Score for "'+data.game+'" (from '+data.player+') : ' + data.score + ' (Undo='+data.undo+') in room '+data.room);
    client.broadcast.to(data.room).emit('score', { game:data.game, score: data.score, undo: data.undo, player: data.player } );
  });

  // Message Emit for private chat
  client.on( 'privatemessage', function( data ) {
    console.log( 'New Message for "'+data.recepient+'" (from '+data.sender+') : ' + data.text);
    client.broadcast.emit('privatemessage', { text:data.text, recepient: data.recepient, sender: data.sender } );
  });

  // Message Emit for Player Room (all)
  client.on( 'openmessage', function( data ) {
    console.log( 'New Message for "Player Room" (from '+data.senderId+') : ' + data.text);
    client.broadcast.emit('openmessage', { text:data.text, senderId:data.senderId, senderAvatar:data.senderAvatar, senderName:data.senderName, senderAvg:data.senderAvg, senderCam:data.senderCam, senderTimestamp:data.senderTimestamp, senderTime:data.senderTime } );
  });

});     

server.listen( 8080 );

If I do a lsof -ni -P to see connection there are indeed a lot of lines by node

COMMAND     PID         USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
...
node      13855         root  273u  IPv4 33761866321      0t0  TCP 83.256.77.109:8080->84.60.76... (ESTABLISHED)
node      13855         root  275u  IPv4 33781428883      0t0  TCP 83.256.77.109:8080->94.197.121...(ESTABLISHED)
node      13855         root  276u  IPv4 33937034956      0t0  TCP 83.256.77.109:8080->79.195.169... (ESTABLISHED)
node      13855         root  278u  IPv4 33971290522      0t0  TCP 83.256.77.109:8080->111.254.157... (ESTABLISHED)
node      13855         root  279u  IPv4 33198279063      0t0  TCP 83.256.77.109:8080->91.48.115... (ESTABLISHED)
...

EDIT 1

I should note that I use php pages. On all php pages which needs the node app I do a connection to the node server.

var socket = io.connect( 'http://example.com:8080' );
socket.on('connect', function( data ) { });

I'm not sure if this is the right way to go, because on every refresh of the page the connection is closed and re-established.

Benmay
  • 347
  • 1
  • 15
  • You need to close your connection, either on the server or on the client (or both) when no longer needed. – Brian White Mar 27 '15 at 16:21
  • Thanks for your answer, I thought the connections (sockets) are closed automatically once the client leave the site (or page which connects to the server), but apparently not. How can I force the closing? – Benmay Mar 28 '15 at 11:21

1 Answers1

0

First, make sure to configure your server correctly. A modern linux has conservative defaults that aren't tuned for high simultaneous connections. There are some pointers here:

How many socket connections possible?

Second, make sure you have a way to 'kick' users off. For example, someone may connect from their cell phone or laptop in a coffee shop, then turn their device off. The TCP connection can remain open for hours or days if there is no traffic. If you don't actively detect them, they will slowly choke off all your valid TCP connections.

Community
  • 1
  • 1
BraveNewCurrency
  • 12,654
  • 2
  • 42
  • 50
  • Thanks for your answer, will have a look at my server settings. How can I 'kick off' the users. – Benmay Mar 28 '15 at 11:37
  • Enable "TCP keepalive" and/or make sure there is a "heart-beat" check going over the connection every few minutes, and close the connection if no data is seen. – BraveNewCurrency Mar 28 '15 at 15:11