# Best-effort sticky sessions

**URL:** <https://www.ruby-forum.com/t/best-effort-sticky-sessions/183915>\
**Category:** NGINX\
**Created:** [February 22, 2010, 4:58pm UTC](https://www.ruby-forum.com/t/best-effort-sticky-sessions/183915 "2010-02-22T16:58:29Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![gnosek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/edb3f5/32.png) [@gnosek](https://www.ruby-forum.com/u/gnosek)\
**Post date:** [February 22, 2010, 4:58pm UTC](https://www.ruby-forum.com/t/best-effort-sticky-sessions/183915/1 "2010-02-22T16:58:29Z")

</div>

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 🙂

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.

---

<div class="post-metadata">

**Author:** ![gnosek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/edb3f5/32.png) [@gnosek](https://www.ruby-forum.com/u/gnosek)\
**Post date:** [February 22, 2010, 5:16pm UTC](https://www.ruby-forum.com/t/best-effort-sticky-sessions/183915/2 "2010-02-22T17:16:03Z")

</div>

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. \< [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) \>

---

<div class="post-metadata">

**Author:** ![gnosek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/edb3f5/32.png) [@gnosek](https://www.ruby-forum.com/u/gnosek)\
**Post date:** [February 22, 2010, 5:18pm UTC](https://www.ruby-forum.com/t/best-effort-sticky-sessions/183915/3 "2010-02-22T17:18:58Z")

</div>

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 🙂

Have a look below, the real problems are the contents of $upstream\_addr  
and fastcgi\_pass $variable behaviour.

Thanks anyway 🙂

Best regards,  
Grzegorz N.
