2010-09-14 16 views
0

J'utilise Nginx avec Phusion Passenger pour exécuter une application Rails sur une machine EC2 CentOS.Comment est-ce que j'obtiens Nginx et Phusion Passenger pour maintenir des sessions entre deux instances de Rails?

J'ai un joli standard mis en place avec Nginx, Rails, Phusion Passenger et SSL (je pense). Mon nginx.conf est ci-dessous. Jusqu'à présent, cela a bien fonctionné, sauf que chaque fois que deux requêtes touchent le serveur en même temps, une nouvelle instance de Rails est créée pour servir la seconde requête. Le problème est qu'une fois que la deuxième requête est dirigée vers l'instance Rails nouvellement créée, elle perd la session authentifiée de l'instance Rails d'origine, ce qui entraîne des erreurs. Mes sessions sont stockées en mémoire.

Pour contourner ce problème, j'ai défini passenger_max_instances_per_app sur 1, de sorte que les nouvelles instances de Rails sont créées, mais ce n'est qu'un correctif temporaire.

Est-ce que quelqu'un sait comment faire Nginx maintenir la même session pour les demandes de la même source? Je pourrais manquer quelque chose d'évident ici.

Merci!

worker_processes 1; 

events { 
    worker_connections 1024; 
} 

http { 
    ... 
    passenger_pool_idle_time 0; 
    passenger_max_instances_per_app 1; 

    include  mime.types; 
    default_type application/octet-stream; 

    sendfile  on; 
    keepalive_timeout 65; 

    # this server isn't rails enabled. 
    # will redirect all traffic to https 
    server { 
     listen  80; 
     server_name example.com; 
     rewrite^https://www.example.com$request_uri permanent; 

     error_page 500 502 503 504 /50x.html; 
     location = /50x.html { 
      root html; 
     } 
    } 

    # HTTPS server 
    # - by default everything is served by https 
    server { 
     listen  443; 
     server_name www.example.com; 
     root /rails/root/public; 
     passenger_enabled on; 
     rails_env production; 

     ssl     on; 
     ssl_certificate  /path/to/cert/www.example.com.crt; 
     ssl_certificate_key /path/to/cert/www.example.com.key; 
     ssl_session_timeout 5m; 
    } 
} 

Répondre

1

Nous avons généralement passenger_max_pool_size 2; à moins que nous laissons en tout (en prenant le réglage par défaut) et les deux paramètres vous spécifiez, et passenger_pool_idle_timepassenger_max_instances_per_app nous laissons également la valeur par défaut.

La clé de session doit être conservée dans un cookie afin que Rails puisse la rechercher entre les requêtes. En supposant que cela fonctionne correctement, le problème est que plusieurs instances de Rails ne partagent pas la mémoire (fonctionnalité, pas un bug - ce sont des processus, pas des threads) et donc ne partagent pas les données de session. Essayez de déplacer vos informations de session dans ActiveRecord:

# Use the database for sessions instead of the cookie-based default, 
# which shouldn't be used to store highly confidential information 
# (create the session table with "rake db:sessions:create") 
ActionController::Base.session_store = :active_record_store 

(le code ci-dessus est en config/initializers/session_store.rb)

De cette façon, parce que le magasin de données est accessiblement à plusieurs processus Rails, ils devraient tous avoir accès à la même piscine des sessions actives.

0

Pour de meilleures performances, vous devriez éviter :active_record_store et l'utilisation memcached à la place

config.action_controller.session_store = :mem_cache_store