Trying to do what it says in the title: retain existing sessions under high load, and serve 503-message to newly arrived visitors.
Problem: it works, but the sessions don't last beyond about 90 seconds.
Current results have me wondering if there's a time-out setting I'm missing.
Purpose
I'm trying to get haproxy to:
- send requests for new sessions to backend-001 when the total number of sessions on the frontend is below a certain threshold.
- serve a 503 error to new sessions when the total number of sessions on the frontend is above that threshold
- allow requests for existing sessions even if the number of sessions exceeds the threshold
This way, visitors that are in the middle of filling in a multi-step form won't be surprised by a 503-error, and new visitors can be told to "please come back later because we're really busy right now".
Setup
The setup is as follows:
{visitors}
↓
[haproxy]
↓
[rails app on unicorn served by nginx] (right now just one
backend: 'backend-001')
current approach
To achieve the above, I'm using the configuration below.
This one is for testing, with a very low limit (10 connections on the front-end (fe_conn gt 10)), to make testing easier.
To put the server under some load, I'm using httperf as follows:
httperf –hog –server staging.machine.tld –uri /do_some_things –wsess=500,10,30 –rate 2
global
daemon
maxconn 10000
defaults
mode http
timeout connect 6s
timeout client 60s
timeout server 60s
balance roundrobin
option http-server-close
frontend http-in
bind [PUBLIC_IP]:80
default_backend backend-001
acl too_many fe_conn gt 10
use_backend b_too_many if too_many
backend backend-001
fullconn 10
appsession _session_id len 128 timeout 7200s
cookie SERVERID insert maxidle 7200s
server Server1 127.0.10.1:80 cookie backend-001 check
backend b_too_many
errorfile 503 /var/www/50x.html
problem
As mentioned above, the problem is: it almost works, but the sessions don't last beyond about 90 seconds.
If you keep clicking about, you get to keep your session even when there are 10 sessions busy.
Trying to open a page on the server with a different browser instance gets you the 503-error.
So, it looks like I'm almost there. Does anyone have an idea what might be causing the short session times?
And particularly how I can fix it 🙂
(edit: removed 'weight 1 maxconn 10' from the 'server'-line, not relevant and might confuse)
(edit the 2nd: corrected '10 sessions on the front-end' to '10 connections on the front-end')
Best Answer
Unfortunately, you appear to be completely confusing connections with application-level sessions. A user visiting the site might have a cookie which makes you think he owns a connection while it's not necessarily the case. He might open as many connections as needed to fetch objects and navigate pages.
The 90 seconds you're observing surely is the browser's keep alive timeout for idle connections.
It is possible to achieve what you want but it's a bit more complex than that, as you have to also consider the presence of the persistence cookie in the request to figure out whether the visitor is a new one or not.
Also in general it's more efficient to rely on the average per-server connection count than on the frontend connection count. The reason is that when a server dies, you need to readjust this number. The most efficient way to do it is to set up a server maxconn value to enable queuing, and to use avg_queue so that the limit applies to the average number of queued requests on servers. This allows you to correctly handle known visitors while softly moving new users to another backend when the load increases due to existing visitors.