Reputation: 10025
Rails application(4.2) is hosted on nginx and serves at localhost:5478. The ip_hash in the code snippet below maintains the server request response consistency and works as expected.
upstream rails {
ip_hash;
To share the load, ip_hash was commented. Now the login for the user starts failing since passing of session cookie is required while works in similar way for Rails3. This is related to something around sticky session but unable to trace the exact way of handling it.
nginx.conf
upstream mongrel {
server 127.0.0.1:5469;
}
upstream rails {
#ip_hash;
server 127.0.0.1:5479;
server 127.0.0.1:5480;
server 127.0.0.1:5481;
server 127.0.0.1:5482;
}
location / {
# Setup redirection headers
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
# Pass the request thru
proxy_pass http://mongrel;
}
}
server {
listen 5478 default;
server_name _;
root "../games/public";
location ~ ^/assets/ {
root "../d2/public";
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
I tried using consistent_hash $scheme $request_uri;
as suggested but consistent_hash as a directive is not recognized and fails. Let me know if any config change is required for nginx. I also found the same nginx config with ip_hash commented works for Rails3 application, not sure if this is related
Upvotes: 1
Views: 3479
Reputation: 423
There are two ways to do this, either:
Let me know if any config change is required for nginx.
if you cannot modify the application, e.g. letting multiple application instances using a common storage, you can try to use sticky
directive of nginx (>=1.5.7).
Using your example, it should be something like
http { ... upstream rails { server 127.0.0.1:5479; server 127.0.0.1:5480; server 127.0.0.1:5481; server 127.0.0.1:5482; sticky rails_sticky expires=1d domain=.rails.local path=/ httponly secure; } ... server { listen 5478; server_name rails.local; root "../games/public"; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://rails; } ... } ... }
You may need to adjust your configuration according to your environment.
Using sticky
, nginx should check and bound a client using a sticky cookie called rails_sticky
, if it's not yet bound. Bounding a client still checks whatever balancing method you set in upstream
directive, weighted round-robin by default.
If client has been bound to a server, any subsequent requests will be forwarded to designated upstream server. In an event that designated upstream server cannot be used, nginx will re-bound the client to another server.
Upvotes: 2