如何让Rails.cache(内存缓存)与Puma一起工作?

12

我正在使用Rails 5.1。我已经在Rails中设置了全局的memory_store缓存。这是在我的config/environments/development.rb文件中进行设置。

  £ Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist?
    config.action_controller.perform_caching = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => 'public, max-age=172800'
    }
  else
    config.action_controller.perform_caching = true
    config.cache_store = :memory_store
  end

这使我能够做一些像这样的事情:

      Rails.cache.fetch(cache_key) do
        msg_data
      end

我的应用程序有两个部分,一个是web socket,另一个是controller。我希望在web socket中获取数据,并在controller中使用该数据。然而,我发现如果我使用puma启动Rails服务器(例如,在config/puma.rb文件中包含以下内容)...

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count

£ Specifies the `port` that Puma will listen on to receive requests, default is 3000.
£
port        ENV.fetch("PORT") { 3000 }

£ Specifies the number of `workers` to boot in clustered mode.
£ Workers are forked webserver processes. If using threads and workers together
£ the concurrency of the application would be max `threads` * `workers`.
£ Workers do not work on JRuby or Windows (both of which do not support
£ processes).
£
workers ENV.fetch("WEB_CONCURRENCY") { 4 }

app_dir = File.expand_path("../..", __FILE__)
shared_dir = "£{app_dir}/shared"

£ Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

£ Set up socket location
bind "unix://£{shared_dir}/sockets/puma.sock"

£ Logging
stdout_redirect "£{shared_dir}/log/puma.stdout.log", "£{shared_dir}/log/puma.stderr.log", true

£ Set master PID and state locations
pidfile "£{shared_dir}/pids/puma.pid"
state_path "£{shared_dir}/pids/puma.state"
activate_control_app





£ Use the `preload_app!` method when specifying a `workers` number.
£ This directive tells Puma to first boot the application and load code
£ before forking the application. This takes advantage of Copy On Write
£ process behavior so workers use less memory. If you use this option
£ you need to make sure to reconnect any threads in the `on_worker_boot`
£ block.
£
£ preload_app!

£ The code in the `on_worker_boot` will be called if you are using
£ clustered mode by specifying a number of `workers`. After each worker
£ process is booted this block will be run, if you are using `preload_app!`
£ option you will want to use this block to reconnect to any threads
£ or connections that may have been created at application boot, Ruby
£ cannot share connections between processes.
£
on_worker_boot do
  require "active_record"
  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  ActiveRecord::Base.establish_connection(YAML.load_file("£{app_dir}/config/database.yml")[rails_env])
end

£ Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

在内存缓存不再有效。换句话说,即使您将数据存储在内存中,当应用程序重新启动时,这些数据也会消失。
Rails.cache.fetch(cache_key)

这段代码总是返回空值。我希望拥有一个多线程的 Puma 环境(最终),以优雅地处理许多请求。但我也希望我的缓存能够正常工作。如何使它们同时协同工作呢?

3个回答

8

在Puma运行于集群模式(即使用多个工作进程)时,你不能使用memory_store。在Rails指南中明确说明了这一点。由于无法在不同进程之间共享内存,因此这显然是有道理的。

如果将Puma工作进程数量降至1不是一个选项,则可以考虑改用Redis或Memcached。在Rails指南中,文档介绍十分完整,你需要向Gemfile添加一个或两个gem,并更新config.cache_store。你需要在服务器上安装相关服务,或者选择使用托管服务提供商(如Heroku Redis、Redis To Go、Memcachier等)来管理它们。


我正在使用Redis。你是说我可以用Redis实现这个内存共享的事情吗? - Dave
1
@Dave:是的。Redis非常适合这个需求。你可能已经拥有了所有需要的gem,唯一需要考虑的是是否想要引入命名空间来保持各个部分的独立性(不确定你在应用程序的哪些其他地方使用它。也许是会话?) - gwcodes
哦,太好了。我正在使用Redis来管理web sockets,将消息发布到频道等等。关于已发布的问题,我需要改变“config.cache_store =:memory_store”以利用Redis吗? - Dave
1
@Dave:在那个Rails指南页面上再往下滚一点:-) http://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-rediscachestore。你需要使用`:redis_cache_store`。 - gwcodes
谢谢兄弟!我要试一下这个。可能需要我几天时间才能回来接受,但我会及时更新我的进展情况。 - Dave
显示剩余3条评论

1

我不知道你能否这样做 - 但无论如何都不要这样做。使用一个真正的缓存服务。例如,memcached。

http://guides.rubyonrails.org/caching_with_rails.html

config.cache_store = :mem_cache_store, "localhost" # assuming you run memcached on localhost

而且...就是这样。


我愿意考虑你的建议,但我需要一些代码示例以及在我发布的代码基础上需要做什么来设置它。 - Dave
我只在单个服务器上运行我的应用程序,因此安装memcached应用程序来处理Rails缓存数据似乎有些过度。如果没有办法通过传统的Rails解决这个问题,我会回来接受。 - Dave
1
你可能认为memcached会拖慢速度,的确会有一些消耗,但微不足道。请记住,我们谈论的是配置有大量CPU/RAM的庞大机器。运行memcached非常容易且高效。几乎所有人都会使用它(或者redis之类的)用于缓存,因为它就是干这个的,而且做得非常好。别去解决已经解决了的问题,你已经有足够的问题要解决了 :-) - kwerle
@Dave - 使用Memcached非常简单。除了config.cache_store之外,您不需要任何其他代码。它是与Redis类似的解决方案。最大的缺点是您必须确保它正在运行,这可能对您来说是问题或不是问题。 - B Seven

0

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