Rails:预定任务来预热缓存?

时间:2011-03-12 13:35:55

标签: ruby-on-rails ruby-on-rails-3 caching memcached

我正在使用以下内容来缓存使用memcached的缓慢加载页面:

caches_action :complex_report, :expires_in => 1.day

控制器操作受Devise身份验证保护。

当前用户首次请求时,页面会被缓存。然后从缓存中提取当天的后续请求。

这个问题是初始请求需要20-30秒才能加载。是否可以通过计划任务预先填充缓存?

任何建议都非常感谢。

4 个答案:

答案 0 :(得分:5)

这是对以前基于cron的解决方案的扩展,该解决方案使用curl存储cookie的能力,以便您可以在一个步骤中进行身份验证,然后在下一步中再次使用cookie作为经过身份验证的用户。因此,如果将这些行放在名为“prepare_cache.sh”的脚本中

rm /tmp/cookiejar
curl --request POST -d "login=<username>" -d "password=<password>" -c /tmp/cookiejar http://yourwebpages.url/login
curl --request GET -b -c /tmp/cookiejar http://yourwebpages.url/page_to_cache
rm /tmp/cookiejar

将登录名和密码参数替换为与登录表单中使用的变量匹配的参数,以及显示要调用的URL。我之前删除了cookiejar,以确保那里没有文件,并在最后将其删除,以确保没有一个cookie,它应该没有访问级别。

然后你可以用cron作业调用这个脚本:

*/15 * * * * /home/myname/prepare_cache.sh > /dev/null 2>&1

希望这应该有效。当我尝试它时似乎为我工作。

答案 1 :(得分:3)

最基本的解决方案可能是设置一个简单的cron条目来加载您希望拥有“热门”缓存的页面。使用crontab打开编辑器,可以轻松地将以下内容添加到服务器上用户的crontab -e

*/15 * * * * wget -q http://yourwebpages.url/ > /dev/null 2>&1

这将使用wget每隔15小时,每天,每月和每年使用提供的网址获取数据,忽略结果,如果出现问题则不发送* nix邮件。

答案 2 :(得分:3)

如果是运行报告和收集结果非常耗时的过程,您可以使用Rails.cache.writeRails.cache.read缓存这些结果(代替或沿着动作缓存)。

然后,因为您不必担心身份验证或向服务器发出请求,所以运行查询和缓存cron作业结果的行为会相当简单。

答案 3 :(得分:3)

看看这个宝石:

https://github.com/tommyh/preheat

gem用于预热Rails.cache。

从文档中: This will "preheat" all your Rails.cache.fetch calls on your homepage. It is as simple as that!

    #app/models/product.rb
    def slow_method
      Rails.cache.fetch("product-slow-method-#{self.id}") do
        sleep 15
        Time.now
      end
    end

    #lib/tasks/preheat.rake
    namespace :preheat do
      desc "Preheat product caches"
      task (:products => :environment) do
        Preheat.it do
          Product.all.each do |product|
            app.get(app.products_path(product)) #or you could just call product.slow_method directly, whatever makes more sense
          end
        end
      end
    end

    #crontab -e
    0 * * * * /path/to/rake preheat:products RAILS_ENV=production 2>&1 >> #{Rails.root}/log/preheat.log &