Ruby on rails HTTP缓存与Rails+;机架::缓存未失效

Ruby on rails HTTP缓存与Rails+;机架::缓存未失效,ruby-on-rails,caching,rack-cache,Ruby On Rails,Caching,Rack Cache,我的Rails 3应用程序生成的页面将在指定的时间段内更改,然后在其余生中保持静态(无更改)(想想:运动记分板) 这似乎是进行完整页面缓存的绝佳机会,因此我选择了Rack::Cache,使用响应的最后修改部分来指示缓存何时无效 缓存工作得很好——太好了。即使最后修改的字段更新的日期/时间晚于请求和响应的If-Modified-Since字段生成的状态200(与304相反),浏览器仍然加载缓存在服务器上的页面版本 以下是我在服务器调试日志中看到的内容: App 16638 stdout: Star

我的Rails 3应用程序生成的页面将在指定的时间段内更改,然后在其余生中保持静态(无更改)(想想:运动记分板)

这似乎是进行完整页面缓存的绝佳机会,因此我选择了Rack::Cache,使用响应的最后修改部分来指示缓存何时无效

缓存工作得很好——太好了。即使最后修改的字段更新的日期/时间晚于请求和响应的If-Modified-Since字段生成的状态200(与304相反),浏览器仍然加载缓存在服务器上的页面版本

以下是我在服务器调试日志中看到的内容:

App 16638 stdout: Started GET "/games/2014/2/10" for xx.xx.xx.xxx at 2014-02-11 04:04:11 +0000
App 16638 stdout: Processing by GamesController#index as HTML
App 16638 stdout:   Parameters: {"year"=>"2014", "month"=>"2", "day"=>"10"}
App 16638 stdout:   Game Load (2.8ms)  SELECT "games".* FROM "games" WHERE "games"."date" = '2014-02-10'
App 16638 stdout:   Game Load (2.8ms)  SELECT "games".* FROM "games" WHERE "games"."id" = 877 LIMIT 1
App 16638 stdout:   Team Load (1.3ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 10 LIMIT 1
App 16638 stdout:   Team Load (0.7ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 23 LIMIT 1
App 16638 stdout:   Game Load (4.2ms)  SELECT "games".* FROM "games" WHERE "games"."id" = 875 LIMIT 1
App 16638 stdout:   Team Load (0.6ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 17 LIMIT 1
App 16638 stdout:   Team Load (5.4ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 2 LIMIT 1
App 16638 stdout:   Game Load (7.0ms)  SELECT "games".* FROM "games" WHERE "games"."id" = 874 LIMIT 1
App 16638 stdout:   Team Load (0.7ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 9 LIMIT 1
App 16638 stdout:   Team Load (7.9ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 27 LIMIT 1
App 16638 stdout:   Game Load (0.7ms)  SELECT "games".* FROM "games" WHERE "games"."id" = 876 LIMIT 1
App 16638 stdout:   Team Load (0.4ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 18 LIMIT 1
App 16638 stdout:   Team Load (0.4ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 11 LIMIT 1
App 16638 stdout:   Game Load (0.6ms)  SELECT "games".* FROM "games" WHERE "games"."id" = 873 LIMIT 1
App 16638 stdout:   Team Load (4.0ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 12 LIMIT 1
App 16638 stdout:   Team Load (0.6ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 8 LIMIT 1
App 16638 stdout:   Game Load (5.4ms)  SELECT "games".* FROM "games" WHERE "games"."id" = 872 LIMIT 1
App 16638 stdout:   Team Load (0.6ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 28 LIMIT 1
App 16638 stdout:   Team Load (3.9ms)  SELECT "teams".* FROM "teams" WHERE "teams"."id" = 19 LIMIT 1
App 16638 stdout: Latest game: 2014-02-11 03:44:50 UTC
App 16638 stdout: Cache read: views/xxxx/games/2014/2/10
App 16638 stdout: Dalli::Server#connect 127.0.0.1:11211
App 16638 stdout: Read fragment views/xxxxx/games/2014/2/10 2.6ms
App 16638 stdout: Completed 200 OK in 618.2ms (ActiveRecord: 128.8ms)
App 15100 stderr: cache: [GET /games/2014/2/10] stale, invalid, store
App 16638 stdout: Started GET "/assets/bootstrap.css" for 66.55.150.181 at 2014-02-11 04:04:12 +0000
App 16638 stdout: Served asset /bootstrap.css - 304 Not Modified (12ms)
App 15100 stderr: cache: [GET /assets/bootstrap.css] stale, valid, store
App 15100 stderr: cache: [GET /assets/application-85cd667c6ae785b5d80f452fe6ad811e.js] fresh
App 15100 stderr: cache: [GET /assets/application-50dd9f33494a58a079e7417a68763e42.css] fresh
以下是一个请求/响应示例(请参见200状态):

在相关的控制器中,我对给定的操作使用before_过滤器,在该过滤器中,我在页面上最后更新的对象上使用fresh_。这似乎在响应中生成了正确的日期/时间,但我包含了所有可能错误的代码(为了简洁起见,我删除了show操作):

class GamesController[:index]
缓存操作:索引
def set_index_cache_头
@date=今天的日期
如果参数[:年]&参数[:月]&参数[:日]
@日期=日期。新建(参数[:年]。到i,参数[:月]。到i,参数[:天]。到i)
其他的
最新游戏=游戏。其中(状态:[:最终,:进行中])。顺序(“日期描述”)。首先
如果是最近的游戏!=无
@日期=最近的比赛日期
结束
结束
@games=Game.where(:date=>@date).compact
@游戏信息=[]
@游戏。每个人都做|
@game_infos.push GameInfo.new(g.id)
结束
@最新游戏=@games.max_by{g|g.updated_at}
Rails.logger.debug“最新游戏:{@Latest_game.updated_at}”
新鲜时(@latest_game,public:true)
结束
def索引
结束
结束

如果我了解您正在尝试什么,我相信您需要将expires\u设置为in(最好设置为after\u筛选器,这样您就不会缓存状态为500的响应)。现在看来,rack cache正在无限期地缓存您的页面(或者不管默认值是什么),并且您的请求永远不会到达rails后端。Rack cache认为您的缓存是“新鲜的”,因此不必麻烦返回重新生成页面。这篇文章很好地解释了它的工作原理:

“fresh_when”仅在您实际通过机架缓存中间件并到达rails层时才被调用。如果您这样做,它将返回304,除非您更新您的记录(@latest_game)


希望对你有帮助,祝你好运!缓存失效是一个难题。

结果是控制器中的这一行:

caches_action :index
他是罪魁祸首。我的意图是只使用Rack::Cache HTTP缓存,但此行激活Rails操作缓存,这不是我的意图。导致问题的原因是两个缓存系统一起运行。拆下此线路后,解决了问题

class GamesController < ApplicationController
  helper ApplicationHelper
  before_filter :set_index_cache_headers, :only => [:index]
  caches_action :index

  def set_index_cache_headers
    @date = Date.today

    if params[:year] && params[:month] && params[:day]
      @date = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i)
    else
      most_recent_game = Game.where(status: [:final, :in_progress]).order("date DESC").first

      if most_recent_game != nil
        @date = most_recent_game.date
      end
    end

    @games = Game.where(:date => @date).compact

    @game_infos = []

    @games.each do |g|
      @game_infos.push GameInfo.new(g.id)
    end

    @latest_game = @games.max_by{|g| g.updated_at}

    Rails.logger.debug "Latest game: #{@latest_game.updated_at}"
    fresh_when(@latest_game, public: true)
  end

  def index

  end
end
caches_action :index