2

I have an Amazon OpsWorks stack running HAProxy (balance = source) and several node.js instances running socket.io. It seems HAProxy determines the max session limit for a given instance based on the memory limits of that instance, which is fine, but my application can often expect clients to be utilising two pages, both connected to a socket, for upwards of 4 hours.

With the max session limit at 40 or 180, I'd only be able to have 20/60 concurrent clients until one disconnects. So with that said, if the limit is reached, other clients will be placed in a queue until a slot becomes free which given the nature of the site is likely to not be for some while. That means I only have a working site for a serious minority.

What's the best way of getting around this? I read several posts where they'll have a backend of 4,000 - 30,000 and a max session limit of just 30 per each server, but how do they achieve this? Is there a setting in HAProxy, or is it more likely they continuously reconnect/disconnect the client either through their actual application?

Edit

To shed some more light on the application - it itself is a PHP application that makes use of sockets for real-time events. These sockets are done so through socket.io with that server being generated using express. This server.js file communicates with an Amazon ElastiCache Redis server (which to my understanding socket.io 1.0 handles all of this backend).

On the client side of things, user's connect to the socket server and emit a connect event so that to join a room unique to them. A user will then load a second page and again emit a connect event and join that same unique room. This then allows for them to emit and receive various events over the course of their session - again, this session can last upwards of 4 hours.

HAProxy routes the user to the same server based upon their IP hash (balance source) - the rest of the options are kept to the OpsWorks default - see the config file below.

http://puu.sh/hvHmb/52177d1e0d.png

I guess what I need to know is if Cur sessions hits 40, and these connections are long-lived (i.e. they don't get readily disconnected), what will happen to those in the queue? It's no good if they are left waiting 4 hours obviously.

--

HAProxy.cfg

global
  log 127.0.0.1   local0
  log 127.0.0.1   local1 notice
  #log loghost    local0 info
  maxconn 80000
  #debug
  #quiet
  user haproxy
  group haproxy
  stats socket /tmp/haproxy.sock

defaults
  log             global
  mode            http
  option          httplog
  option          dontlognull
  retries         3
  option          redispatch
  maxconn        80000
  timeout client 60s             # Client and server timeout must match the longest
  timeout server 60s             # time we may wait for a response from the server.
  timeout queue  120s              # Don't queue requests too long if saturated.
  timeout connect 10s           # There's no reason to change this one.
  timeout http-request 30s  # A complete request may never take that long.
  option          httpclose                                         # disable keepalive (HAProxy does not yet support the HTTP keep-alive mode)
  option          abortonclose                                      # enable early dropping of aborted requests from pending queue
  option          httpchk                                           # enable HTTP protocol to check on servers health
  stats auth strexm:OYk8834nkPOOaKstq48b
  stats uri /haproxy?stats

# Set up application listeners here.
listen application 0.0.0.0:80
  # configure a fake backend as long as there are no real ones
  # this way HAProxy will not fail on a config check
  balance source
  server localhost 127.0.0.1:8080 weight 1 maxconn 5 check

Server.js

var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: ###, port: 6379 }));

server.listen(80); // opsworks node.js server requires port 80

app.get('/', function (req, res) {
   res.sendfile('./index.html');
});

io.sockets.on('connection', function (socket) { 
    socket.on('join', function(room) {
        socket.join(room);
    });

    socket.on('alert', function (room) {
        socket.in(room).emit('alert_dashboard');
    });

    socket.on('event', function(data) {
        socket.in(data.room).emit('event_dashboard', data);
    });
});

Client

var socket = io.connect('http://haproxy_server_ip:80');
socket.on('connect', function() {
    socket.emit('join', room id #);
});
J Young
  • 121
  • 1
  • 5

2 Answers2

0

I don't think haproxy sets these limits. I have a suspicion that there may be limit on how many session from same the ip address are allowed, so if you are testing it from a single machine then that would likely be your problem. Haproxy indeed can easily handle 10th of thouthands connections.

dtoubelis
  • 4,579
  • 1
  • 28
  • 31
  • Ah, that's possible. I did test it by opening 40 windows myself and then having several others connect - they were placed in the queue until it came to a point where I had less than 40 windows. It's probably not the most elegant way to test admittedly, I guess it's time to look into a httperf or something. – J Young Apr 29 '15 at 23:12
0

Without seeing any configs that you are talking about and what sites you are talking about I have to guess they are achieving the number of sessions on a standard web app with http-server-close. So in that case you have a large number of short lived connections.

A better example of what you are doing is web sockets, which are very long lived connections. For the SE network we have our maxconns for our web socket tier set to 500,000.

What you really want to do is figure out how many concurrent connections you want to be able to support at any given time, and set your maxconn value to that. Of course you'll have to make sure that you have enough resources on your load balancer to support the number you select.

slm
  • 7,355
  • 16
  • 54
  • 72
Zypher
  • 36,995
  • 5
  • 52
  • 95
  • Right OK. OpsWorks sets it to 8000 by default (which at this early stage is ample), but just to clarify, despite each user having a long lived connection, as long as they are not emitting or receiving, will they effectively become a ghost user in the sense that there is the allowance for other users to still receive and emit? I've updated my main post to shed a little more light on the nature of the application. I appreciate your help! – J Young Apr 29 '15 at 23:40