我们有一个 Rails 3.2 网站,该网站相当大,有数千个 URL。我们为 Russian Doll 缓存实现了 Cache_Digests gem。它运作良好。我们希望通过夜间预热缓存来进一步优化,以便用户在白天获得更好的体验。我看到了这个问题的答案:Rails: Scheduled task to warm up the cache?
是否可以对其进行修改以预热大量 URL?
最佳答案
要以昂贵的加载时间触发许多页面的缓存命中,只需创建一个 rake 任务以迭代地将 Web 请求发送到站点内的所有记录/URL 组合。 (Here is one implementation)
迭代地 Net::HTTP
请求所有站点 URL/记录:
要仅访问每个页面,您可以每晚运行 Rake 任务,以确保清晨用户仍然拥有包含刷新内容的快速页面。
lib/tasks/visit_every_page.rake:
namespace :visit_every_page do
include Net
include Rails.application.routes.url_helpers
task :specializations => :environment do
puts "Visiting specializations..."
Specialization.all.sort{ |a,b| a.id <=> b.id }.each do |s|
begin
puts "Specialization #{s.id}"
City.all.sort{ |a,b| a.id <=> b.id }.each do |c|
puts "Specialization City #{c.id}"
Net::HTTP.get( URI("http://#{APP_CONFIG[:domain]}/specialties/#{s.id}/#{s.token}/refresh_city_cache/#{c.id}.js") )
end
Division.all.sort{ |a,b| a.id <=> b.id }.each do |d|
puts "Specialization Division #{d.id}"
Net::HTTP.get( URI("http://#{APP_CONFIG[:domain]}/specialties/#{s.id}/#{s.token}/refresh_division_cache/#{d.id}.js") )
end
end
end
end
# The following methods are defined to fake out the ActionController
# requirements of the Rails cache
def cache_store
ActionController::Base.cache_store
end
def self.benchmark( *params )
yield
end
def cache_configured?
true
end
end
通过自定义 Controller 操作:
如果您需要绕过用户身份验证限制才能访问您的页面,和/或您不想搞砸(太严重)您网站的跟踪分析,您可以创建 custom controller action用于命中缓存摘要 use tokens to bypass authentication :
app/controllers/specializations.rb:
class SpecializationsController < ApplicationController
...
before_filter :check_token, :only => [:refresh_cache, :refresh_city_cache, :refresh_division_cache]
skip_authorization_check :only => [:refresh_cache, :refresh_city_cache, :refresh_division_cache]
...
def refresh_cache
@specialization = Specialization.find(params[:id])
@feedback = FeedbackItem.new
render :show, :layout => 'ajax'
end
def refresh_city_cache
@specialization = Specialization.find(params[:id])
@city = City.find(params[:city_id])
render 'refresh_city.js'
end
def refresh_division_cache
@specialization = Specialization.find(params[:id])
@division = Division.find(params[:division_id])
render 'refresh_division.js'
end
end
我们的自定义 Controller 操作会呈现其他加载成本高昂的页面的 View ,从而导致这些页面的缓存命中。例如。 refresh_cache
呈现与 controller#show 相同的 View 页面和数据,因此请求 refresh_cache
将为这些记录预热与 controller#show 相同的缓存摘要。
安全说明:
出于安全原因,我建议在提供对您传入 token and check it 的任何自定义 refresh_cache
Controller 请求的访问权限之前确保it corresponds with a unique token for that record.在提供访问权限之前将 URL token 与数据库记录进行匹配(如上所示)非常简单,因为您的 Rake 任务可以访问每条记录的唯一 token - 只需在每个请求中传递记录的 token 即可。
tl;博士:
要触发数千个站点 URL/缓存摘要,请创建一个 rake 任务来迭代请求站点中的每个记录/URL 组合。您可以通过创建一个自定义 Controller 操作(通过 token 对访问进行身份验证)来绕过应用对此任务的用户身份验证限制。
关于caching - 过夜预热缓存摘要,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29301780/