Run multiple socket.io-clients in one node.js instance - node.js

I want to run stress tests using node.js, socket.io, and socket.io-client.
I want to get the network bandwidth, processor/memory use, etc.
I have a node.js socket.io server on amazon, size XLARGE.
Now I want to run multiple socket.io-clients in other amazon servers, and connect them to my server.
I was running it in different processes, but one node.js process takes 15MB memory. I want to test 100k socket.io connections simultaneously, so this is not an option.
My question is: Can I run, for example, 60k different socket.io-clients in one node.js instance?
This is my client code:
var socket = require('socket.io-client')('http://someAddress:3000');
socket.on('connect', function(){
socket.on('news', function(data){
});
socket.emit('event', { data: "Connection test." });
});

You have to pass forceNew option:
var socket = require('socket.io-client')('http://someAddress:3000', {
forceNew: true
});
And then initialize your sockets in a loop.
Here is a full test example:
server.js:
var io = require('socket.io')();
io.on('connection', function(socket){
var i = 0;
setInterval(function() {
socket.emit('news', {
message: i++
});
}, 1000);
});
io.listen(3000);
client,js:
function testOne() {
var socket = require('socket.io-client')('http://127.0.0.1:3000', {forceNew: true});
socket.on('connect', function(){
socket.on('news', function(data){
console.log(data.message);
});
});
}
for (var i = 0; i < 5; i++) {
testOne();
}
For testing purpose I've made client to output incrementing number for five times each second.

Related

Memory leak when running Nodejs socket.io on AWS EC2 t2.micro

I want to check the max connections for websocket that t1.micro instance (1GB RAM) can be handle.
So I simple example to check it with nodejs(v6.2.1) and socket.io#1.4.6.
Here is the code on server:
require("http").globalAgent.maxSockets = Infinity;
var http = require('http').createServer(function(req, res) {});
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('echo me', function (data) { //receive msg from client
var msg = {msg: data.msg};
io.emit('echo me', msg);
delete msg.msg;
});
});
var clock = setInterval(function(){
global.gc();
}, 2000);
http.listen(3000, function(){
console.log('listening on *:3000');
});
And code on client
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script type="text/javascript">
var n = 20;
var socket = [], id = [];
for(var i = 0; i < n; ++i){
socket[i] = io('http://aws_ip_address');
socket[i].on('connect', function(){
id.push(this.io.engine.id);
console.log('Connected to Server. My name is ');
});
socket[i].on('echo me', function(data){ //receive message from server
console.log(data.msg);
});
}
var inv = setInterval(function(){
sendEchoToServer();
}, 1000); //1 second
function sendEchoToServer(){
for(var i = 0; i < n; ++i){
var msg = 'My name is ' + id[i] + ' with msg: ' + Math.random();
socket[i].emit('echo me', {msg: msg});
}
}
</script>
The problem I got. When I open 10 tabs (200 connections) on clients, the memory increase minutes by minutes. And if I open 350 connections, the server can't handle in 5 minutes (The OS kill it). The CPU getting 100%.
I want it can handle more than 500 connections, is it possible?
Thanks in advanced.
You can change the memory handling in node to be more agressive.
More on the options available:
https://gist.github.com/listochkin/10973974​
node --expose-gc --optimize_for_size --max_old_space_size=460 --gc_interval=100 app.js

Socket.IO - setInverval every two minutes (Node JS)

I have an event in socket.io which broadcasts how many users are online (based on who is logged in) to the user.
What I think should be happening is that I ask the server to query the database once every two minutes using setInterval, and a rowset is returned, then emitted to the client.
What is happening though, is that for each user connected to the socket, it is calling the database on the server and pushing to the client.
I'm uncertain why this is doing this - I'd understand if I was asking it to do this from the client, but as it's the server emitting the event to the client, why would it be doing this several time for each user connected?
Thanks
io.on("connection", function(socket) {
// Update online users' every two minutes
setInterval(function() {
var roomNum = 0;
var outObj = {};
model.get_online_users(function(err, rowset) {
// Loop thorugh the rowset, set the roomNum and built up out_obj to output
io.to("room_number:"+roomNum).emit("online-users", outObj);
}); // End `model callback`
}, 120000); // End `get_online_users`
}); // End `io.on("connection")`
The code in io.on("connection", function(socket) { something(); }); is called for EVERY connected user, if you put a loop in this, the loop will loop paralelly for every connected user.
The setInterval should be outside of your io.on("connection", function(socket) { });, and it will run once, from your node server starting to the shutdown of the server.
Example :
setInterval(function() {
var roomNum = 0;
var outObj = {};
model.get_online_users(function(err, rowset) {
io.to("room_number:"+roomNum).emit("online-users", outObj);
});
}, 120000);

getConnections method of node.js tcp server not defined

var server = net.createServer(function(c) {
...
})
server.getConnections(function(err, count){
console.log("count", count);
})
I get the following error.
Object #<Server> has no method 'getConnections'
How to use getConnections of a tcp server?
I'm using node version v0.10.16
I'm not sure exactly why your code doesn't work. While having the request to getConnections outside of the connection callback is not necessary typical, it worked in my tests. server.connections is deprecated per the documentation, so it's use is discouraged.
Using telnet localhost 1337, a really poor echo socket is emulated below, and the current count of connections is displayed. The code below worked in my tests:
var server = require('net').createServer();
server.on('connection', function (socket) {
socket.on('data', function(data) {
socket.write(data);
});
server.getConnections(function(err, count) {
console.log("Connections: " + count);
});
});
server.listen(1337);
You can try like this:
var net = require('net');
var events = require('events');
var eventEmitter = new events.EventEmitter();
var server = net.createServer(function(c) {
...`enter code here`
eventEmitter.emit('event1');
})
eventEmitter.on('event1', function(){
server.getConnections(function(err, count){
console.log("count", count);
})
});

node.js application suddenly loads CPU at 100% and hangs

I have simple application on node.js running on linux virtual machine. It listens for tcp messages and sending them to the clients using socket.io library. And after some time of low CPU usage it suddenly starts to load CPU higher and higher until application hangs up. The script is simple and I can not understand what's wrong with it.
var net = require('net');
var io = require('socket.io').listen(socketPort);
net.createServer(function (socket) {
socket.setEncoding("utf8");
socket.on('data', function (dataStr) {
console.log("TCP dataStr " + dataStr);
var data = JSON.parse(dataStr);
io.sockets.in(data.room).emit('publish', data);
});
}).listen(tcpPort);
io.sockets.on('connection', function (socket) {
socket.on('subscribe', function (room) {
console.log('subscribe room ' + room);
if (Array.isArray(room)) {
var i;
for (i = 0; i < room.length; i++) {
console.log('subscribe join room ' + room[i]);
socket.join(room[i]);
}
} else if (typeof room === 'string') {
console.log('subscribe join room ' + room);
socket.join(room);
}
});
socket.on('unsubscribe', function (room) {
console.log('unsubscribe room ' + room);
if (Array.isArray(room)) {
var i;
for (i = 0; i < room.length; i++) {
console.log('unsubscribe leave room ' + room[i]);
socket.leave(room[i]);
}
} else if (typeof room === 'string') {
console.log('unsubscribe leave room ' + room);
socket.leave(room);
}
});
});
Also with cluster module I tried to run multiple workers that communicate with clients. And every worker after some time hangs own CPU core at 100% with time difference in about a minute.
UPD: Client code (run in browser):
socketObj = new function() {
var that = this;
that.socket;
that.init = function(nodeServerUrl, rooms, onPublishFunc) {
that.socket = io.connect(nodeServerUrl);
that.socket.emit('subscribe', rooms);
that.socket.on('publish', function(data) {
onPublishFunc(data);
});
};
that.subscribe = function(room) {
that.socket.emit('subscribe', room);
};
that.unsubscribe = function(room) {
that.socket.emit('unsubscribe', room);
};
}
...
try {
socketObj.init('application url', ["room1", "room2"], nodeJsCallback);
} catch(err) {
}
...
nodeJsCallback = function(jsonData) {
//Only updates data on UI, no subscribing, unsubscribing, emitting etc.
...
}
UPD2: I tried to reproduce the problem with synthetic tests on production machine and on my local Windows machine. I have done some stress testing:
Multiple client socket connections
Multiple static data downloads (socket.io script for browser)
Increased frequence of tcp updates.
After few hours of testing I failed to reproduce. But when it is running on production with real users, it is hanging up earlier or later.
I'm starting to think this is either environment or specific message problem. Probably next things I'll try are:
Update Node.js to current version
Try to log all data transfer and replay it later hoping hanging will reproduce
Changed Nodejs from version v0.10.4(Stable) to v0.11.2(Unstable). All woking good so far, consuming 1-2% CPU. Now we are testing on v0.10.8(Stable).
UPD On v0.10.8 application is stable too.
Even though the problem dissapeared on v0.10.4(Stable), it is still very strange and discouraging.

node.js setInterval doesn't work

With node.js, I'm trying to send the current server_time to all clients in every second.
Therefore, I wanted to use setInterval() to emit an event to all clients and sending the time, but it doesn't work. Did I define the setInterval function at the right place or did missed something else?
var http = require("http");
var socketIO = require('socket.io');
var connect = require('connect');
//keep track of every connected client
var clients = {};
//create Server
var httpServer = connect.createServer(
connect.static(__dirname)
).listen(8888);
//socket
var io = socketIO.listen(httpServer);
io.sockets.on('connection', function (socket) {
//add current client id to array
clients[socket.id] = socket;
socket.on('close', function() {
delete clients[socket.fd]; // remove the client.
});
//send news on connection to client
socket.emit('news', { hello: 'world' });
//this one works fine!
//send server time on connection to client
socket.emit("server_time", { time: new Date().toString() });
});
//this doesn't work!
// Write the time to all clients every second.
setInterval(function() {
var i, sock;
for (i in clients) {
sock = clients[i];
if (sock.writable) { // in case it closed while we are iterating.
sock.emit("server_time", {
console.log("server_time sended");
time: new Date().toString()
});
}
}
}, 1000); //every second
May I suggest a workaround/improvement that should fix the problem. Add the clients to a chat room. Somewhere in:
io.sockets.on('connection', function (socket) {
add a
socket.join('timer');
Then the setIntervall would be
setInterval(function() {
io.sockets.in('timer').emit("server_time", { time: new Date().toString() })
}, 1000);
Hope this works for you!
The problem is the following function:
if (sock.writable) { // in case it closed while we are iterating.
sock.emit("server_time", {
// console.log("server_time sended"); // get rid of this line -> invalid code
time: new Date().toString()
});
}
sock.writable is undefined and therefore the emit event is never sent. Set the property to true on connection and to false on close.

Resources