Best-effort sticky sessions

Hi all,

I’m trying to implement sticky sessions with Nginx 0.7.65 (basically
vanilla, regarding HTTP support) and I need something better than
ip_hash. When a backend is reported as down (the haproxy that Nginx is
proxying to seems to behave strangely even though the load is rather
low), an ip_hash upstream tries the other backend (I have just two
configured). This caused dropped sessions and lost attachments (it’s a
rather busy webmail application). We now keep sessions in memcached so
the problem is not as severe but there is still the risk of misdirecting
traffic. Sharing the attachment area is currently out of the question so
please refrain from suggesting that :slight_smile:

What I’d like to have would look roughly like this (apart from
completely not working):

upstream up1 {
server sv1:9000;
server sv1:9000; # try again (and possibly again…)
server sv2:9000; # and finally fail over to the other server
}

upstream up2 {
server sv2:9000;
server sv2:9000; # try again (and possibly again…)
server sv1:9000; # and finally fail over to the other server
}

upstream default {
server sv1:9000; # round-robin (or ip_hash, or just about
server sv2:9000; # anything)
}

map $cookie_serverid $upstream {
sv1 up1;
sv2 up2;
default default;
}

map $upstream_addr $serverid {

$upstream_addr contains a sorted ", "-separated list of

configured backends (ip:port), rendering it completely useless

for my nefarious plans

I’d have expected ip:port of the final chosen backend here

sv1:9000 sv1;
sv2:9000 sv2;
}

location / {
fastcgi_pass $upstream; # using a $variable makes fastcgi_pass
# expect ip:port, apparently
add_header Set-Cookie serverid=$serverid;
}

So, without some deep sourcery (which I’d rather avoid), can I have
sticky sessions with Nginx trying really hard to avoid other backends?
I guess I could hack something together with the embedded Perl module…

Best regards,
Grzegorz N.

Hi Grzegorz,

upstream up1 {
server sv1:9000;
server sv1:9000; # try again (and possibly again…)
server sv2:9000; # and finally fail over to the other server
}

Unless I’ve missed something, this should work for your use-case:

upstream up1 {
server sv1:9000 max_fails=3;
server sv2:9000 backup;
}

Best regards,
Piotr S. < [email protected] >

On Mon, Feb 22, 2010 at 05:15:15PM +0100, Piotr S. wrote:

upstream up1 {
server sv1:9000 max_fails=3;
server sv2:9000 backup;
}

You’re right but it just makes the config prettier and still broken :slight_smile:

Have a look below, the real problems are the contents of $upstream_addr
and fastcgi_pass $variable behaviour.

Thanks anyway :slight_smile:

Best regards,
Grzegorz N.