当会话存储在memcached(Rails)中时,用户会接管其他用户的会话。

14

我在使用 Memcached 存储 session 的时候,遇到了一个非常奇怪的问题。偶尔会出现某些用户获取到了其他用户的 session,比如 John 登录后变成了 Maria,Maria 变成了 Chris 等等。

我使用的是 Rails 2.3.4,但之前的版本也存在这个问题。我只使用了一台 Memcache 服务器,而且它和我的应用运行在同一台机器上。调试这个问题的困难在于我无法复现它。

如果有人能指导我如何解决或调试这个问题,我将不胜感激。如果你正在使用 Memcached 来存储 session,并可以分享你的示例配置,我也会很高兴的。

以下是我的配置:

# memcache options
memcache_options = {
  :c_threshold => 10_000,
  :compression => false,
  :debug => false,
  :namespace => 'app_prod',
  :readonly => false,
  :urlencode => false,
}
memcache_servers = ['localhost:11211']

CACHE = MemCache.new(memcache_options)
CACHE.servers = memcache_servers

config.cache_store = :mem_cache_store, memcache_servers, memcache_options
config.action_controller.session_store = :mem_cache_store
config.action_controller.session = {
  :session_key => '_appname',
  :cache => CACHE,
#    :expires => 10,
#    :session_expires => 10,
  :secret      => '5391aaaaaaaaaa56f8e8234beb638b97b32bbbbbbbbbbcc9dcae2beccccccccc89e8b508328def001a368da0678b061eb0e9d5a82a5ac94c8d35bd31a9a49e1'
}

事先感谢您,
Stan

5个回答

5

是的,我使用Passenger。 我会在我的两个应用程序上进行测试,并在这里分享结果。 非常感谢您的帮助。我可以“嗅出”问题就在这里。 - Stan Bright
我羡慕你的鼻子,但在结果得到验证之前,我不会将答案标记为正确。 - Andriy Volkov

3

这里是解决我的问题的代码:

我在

environment.rb

的末尾添加了这些行:

if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      CACHE.reset
      if Rails.cache.class == ActiveSupport::Cache::MemCacheStore
        Rails.cache.instance_variable_get(:@data).reset
      end
    end
  end
end

3
这可能是会话cookie在两个值之间切换的问题。例如,您可能已经分配了一个给example.com,另一个给www.example.com,在某些响应两者而没有重定向为一个规范的网站上很常见。
某些浏览器的行为是发送与最长子域匹配的cookie,而其他浏览器实际上会通过两个值发送,这两个值可能不同。这可能导致会话在不可预知的时间内在两个不同的值之间切换。
修复此问题的一种方法是将cookie锁定到.domain.com,而不是让它假定www或无www版本,如果是这种情况,或者重定向以强制仅使用一个版本。
诊断会话问题性质的另一种方法是拥有一个显示会话ID的调试页面,或者以某种方式将其嵌入页面输出中,以便遇到问题的人可以帮助诊断。像/session_info这样的东西很容易创建。

好的,我有这个配置选项: ActionController :: Base.session_options [: session_domain] ='.mysite.com'我认为这个配置选项意味着应用程序将必须为所有子域使用一个会话,包括主域(mysite.com)。另外,如果我看到有问题的用户的session_id,您能给出进一步的建议吗? - Stan Bright
这是正确设置cookie的方式,所以应该可以正常工作。如果你想冒险一试,可以查看production.log文件,了解使用哪些session_id值。通常当一个用户切换到另一个用户时,会因为session混淆而发生。如果不是这种情况,至少你可以将搜索重点放在其他领域。 - tadman
是的,我认为会话被搞混了,我正在寻找解决此问题的方法。 - Stan Bright

2

我以前从未遇到过这样的问题,我甚至无法想象它正在发生。这是我的配置:

require 'memcache'

memcache_options = {
  :c_threshold => 10_000,
  :compression => true,
  :debug => false,
  :namespace => "app-me",
  :readonly => false,
  :urlencode => false
}
memcache_servers = [ "#{MEMCACHED_HOST}:#{MEMCACHED_PORT}" ]

CACHE = MemCache.new memcache_options

CACHE.servers = memcache_servers
ActionController::Base.session_options[:expires] = 1800
ActionController::Base.session_options[:cache] = CACHE

# Inside the Rails initializer
config.action_controller.session_store = :mem_cache_store

正如您所看到的,我的memcache_options唯一的区别是我不使用:compression。然而,我认为这不应该是一个问题。在两个有会话问题的应用程序中,我配置了这样的重定向:http://www.mysite.com => http://mysite.com。您的域名/子域名是否有重定向? - Stan Bright

0

Dalli宝石可能会有所帮助。最近期的提交修复了套接字共享,因此您可以查看他们的代码并了解他们是如何做到的。


在我使用Dalli gem的Ruby 2.3 Rails 4.2.5中,这仍然发生。 - Nick M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接