4

在旧的 Rails 项目中,页面缓存的工作方式与我从在线阅读文档中所期望的一样,但在 Rails 3.1 / 3.2 中,它的工作方式不同。看起来 Rails 将页面写入磁盘但从不使用它们(所以我假设它是在内存中缓存页面)。

(请耐心等待我的冗长解释,它并不复杂,只是彻底......)

在一个新的 Rails 3.2.2 应用程序中,我有以下内容:

class HomeController < ApplicationController
  caches_page :index
  def index
    expires_in 1.year, :private => false, :public => true
  end
end

当我在生产中启动服务器并访问 localhost 时,我看到:

cache: [GET /] miss, store


Started GET "/" for 127.0.0.1 at 2012-03-02 12:19:22 -0500
Processing by HomeController#index as HTML
  Rendered home/index.html.erb within layouts/application (20.0ms)
Write page /home/sheldon/Dev/rails-3.2-app/public/index.html (0.4ms)
Completed 200 OK in 30ms (Views: 28.7ms | ActiveRecord: 0.0ms)

文件 public/index.html 出现在磁盘上。

我正在使用 Firefox,如果我 ctrl+r 或 shift+ctrl+r 我看到:

cache: [GET /] fresh
[2012-03-02 12:21:39] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true

如果我直接编辑 public/index.html 文件并点击 ctrl+r 或 ctrl+shift+r 我看不到我对文件所做的更改。

如果我打开一个 Rails 控制台并输入,Rails.cache.clear我会看到:

=> ["/home/sheldon/Dev/rails-3.2-app/tmp/cache/9F4", "/home/sheldon/Dev/rails-3.2-app/tmp/cache/A9A"]

现在,如果我 ctrl+r 或 ctrl+shift+r 我看到:

cache: [GET /] miss, store


Started GET "/" for 127.0.0.1 at 2012-03-02 12:37:04 -0500
Processing by HomeController#index as HTML
  Rendered home/index.html.erb within layouts/application (0.0ms)
Write page /home/sheldon/Dev/rails-3.2-app/public/index.html (0.3ms)
Completed 200 OK in 2ms (Views: 1.2ms | ActiveRecord: 0.0ms)

我对 public/index.html 的更改被覆盖。

因此,似乎从未使用过 public/index.html 。

如果我编辑在 tmp/cache 中找到的 html 文件(在上面的控制台输出中),然后 ctrl+r 或 ctrl+shift+r 我仍然看不到我直接对 tmp/cache 文件所做的更改。

如果我设置config.cache_store = :file_store, Rails.public_path + "/cache"行为似乎相同。

在入门 Rails 指南中它说“Rails 将在公共目录中提供任何静态文件,而不是我们从控制器生成的任何动态内容”,但显然情况并非如此。

该页面似乎仅缓存在内存中,并且未使用磁盘上的文件...谁能解释这里发生了什么以及如何在磁盘上缓存页面?将所有页面缓存在内存中是不切实际的。谢谢!

4

2 回答 2

2

有两种形式的缓存正在进行:

  • Rack::Cache
  • 页面缓存

页面缓存是caches_page打开的,并在 /public 中写入文件。页面缓存是愚蠢的,因为一旦该文件存在,它将继续提供服务,直到有东西将其删除。好处是它非常快:您通常配置 nginx、apache 等来直接提供这些文件,而不会请求 ruby​​。如果您没有运行 nginx 或 apache,那么只有在将 rails 配置为提供静态资产时才会提供该文件,这在生产中默认是关闭的(请参阅 参考资料config.serve_static_assets

Rack::Cache是一个 http 感知缓存,因此它可以处理到期时间,告诉您和用户之间可能存在的中间缓存他们可以缓存什么等。它将其缓存的数据存储在您配置的任何存储Rails.cache中(文件存储由外观其中)。任何请求仍然必须通过 ruby​​,以便 Rack::Cache 可以决定是否返回缓存数据或是否让请求继续到您的应用程序。

于 2012-03-03T00:23:48.930 回答
0

这是我尝试的设置,我认为它会做我想做的一切:

config.cache_store = :dalli_store, '127.0.0.1:11211'

config.middleware.delete Rack::Cache
config.middleware.use Rack::Cache,
  :verbose => true,
  :metastore => "memcached://127.0.0.1:11211/meta",
  :entitystore => "file:#{Rails.root}/tmp/cache/rack/body"

config.action_controller.page_cache_directory = "#{Rails.root}/public/cache"

起初这似乎可行,但是当页面陈旧但有效(即返回 304)时,我开始收到空白页面。我找不到解决这个问题的方法,所以......我不知道如何设置 Rack::Cache 以使用文件存储,同时仍然保留将 memcached 与 Rails.cache 一起使用的选项。

I'm now using Rails page caching for most of the site. Unfortunately this has the drawback of maintaining complicated sweepers and it also means pages that require query params will have to be cached in memory with expires_in, and fresh_when/stale.

于 2012-03-07T19:09:12.157 回答