简体   繁体   English

如何让Nginx和Phusion Passenger维护两个Rails实例之间的会话?

[英]How do I get Nginx and Phusion Passenger to maintain sessions between two Rails instances?

I'm using Nginx with Phusion Passenger to run a Rails app on an EC2 CentOS machine. 我将Nginx与Phusion Passenger结合使用,以在EC2 CentOS计算机上运行Rails应用程序。

I have a pretty standard set up with Nginx, Rails, Phusion Passenger and SSL (I think). 我为Nginx,Rails,Phusion Passenger和SSL(我认为)建立了相当不错的标准。 My nginx.conf is below. 我的nginx.conf在下面。 So far it has worked out fine except that every time two requests hit the server at the same time, a new Rails instance is created to serve the second request. 到目前为止,它工作得很好,只是每次两个请求同时到达服务器时,都会创建一个新的Rails实例来服务第二个请求。

The problem is that once the second request is directed to the newly created Rails instance, it loses the authenticated session from the original Rails instance, resulting in errors. 问题在于,第二个请求一旦定向到新创建的Rails实例,它将失去原始Rails实例的经过身份验证的会话,从而导致错误。 My sessions are stored in memory. 我的会话存储在内存中。

As a workaround, I've set passenger_max_instances_per_app to 1 so on new Rails instances are created, but this is only a temporary fix. 作为一种解决方法,我将passenger_max_instances_per_app设置为1,这样就可以创建新的Rails实例,但这只是一个临时解决方案。

Does anyone know how to make Nginx maintain the same session for requests from the same source? 有谁知道如何使Nginx为来自相同来源的请求维护相同的会话? I might be missing something obvious here. 我可能在这里缺少明显的东西。

Thanks! 谢谢!

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;
    }
}

We generally have passenger_max_pool_size 2; 我们通常有passenger_max_pool_size 2; unless we leave it out entirely (taking the default setting) and the two settings you're specifying, passenger_pool_idle_time and passenger_max_instances_per_app we also leave to the default. 除非我们完全省略(采用默认设置)和您指定的两个设置( passenger_pool_idle_timepassenger_max_instances_per_app ),否则我们也保留默认设置。

The session key should be kept in a cookie so Rails can look it up between requests. 会话密钥应保存在cookie中,以便Rails可以在请求之间进行查找。 Assuming that's working properly, the problem is that multiple Rails instances aren't sharing memory (feature, not a bug - they're processes, not threads) and therefore don't share session data. 假设工作正常,问题在于多个Rails实例不共享内存(功能,不是错误-它们是进程,不是线程),因此不共享会话数据。 Try moving your session information into ActiveRecord: 尝试将会话信息移到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

(the above code is in config/initializers/session_store.rb ) (以上代码在config/initializers/session_store.rb

That way, because the data store is accessibly to multiple Rails processes, they should all have access to the same pool of active sessions. 这样,由于数据存储可访问多个Rails进程,因此它们都应有权访问相同的活动会话池。

为了获得更好的性能,应避免使用:active_record_store ,而应使用memcached

config.action_controller.session_store = :mem_cache_store

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM