在Heroku部署上清除Memcached

时间:2011-10-11 21:53:25

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

将rails应用程序部署到Heroku时,自动清除Memcached的最佳方法是什么?

我正在缓存主页,当我进行更改并重新部署时,页面将从缓存中提供,并且不会包含更新。

我想让它完全自动化。我不希望每次部署时都必须清除heroku控制台中的缓存。

谢谢!

9 个答案:

答案 0 :(得分:32)

我使用bash脚本部署我的应用程序,该脚本自动化GitHub& Heroku推送,数据库迁移,应用程序维护模式激活和缓存清除操作。

在此脚本中,清除缓存的命令为:

heroku run --app YOUR_APP_NAME rails runner -e production Rails.cache.clear

这适用于Celadon Cedar和Heroku Toolbelt包。我知道这不是基于Rake的解决方案,但它非常有效。

注意:请确保将environment命令的-e / runner选项设置为production,因为它将在development上执行

编辑:几天后我在Heroku上遇到过这个命令的问题(Rails 3.2.21)。我没有时间检查问题的根源,但删除-e production做了伎俩,所以如果命令不成功,请运行此命令:

heroku run --app YOUR_APP_NAME rails runner Rails.cache.clear

答案 1 :(得分:23)

[在Celadon Cedar Stack上]

- [2012年6月18日更新 - 这不再有效,将会看到我是否可以找到另一种解决方法]

我发现处理这些部署后挂钩的最简洁方法是锁定资产:在slug编译期间已经调用的预编译任务。点头对asset_sync Gem提出了这个想法:

Rake::Task["assets:precompile"].enhance do
  # How to invoke a task that exists elsewhere
  # Rake::Task["assets:environment"].invoke if Rake::Task.task_defined?("assets:environment")

  # Clear cache on deploy
  print "Clearing the rails memcached cache\n"
  Rails.cache.clear
end

我只是将它放在lib / tasks / heroku_deploy.rake文件中,它很好地被拾取。

答案 2 :(得分:8)

我最终做的是创建一个新的rake任务,该任务部署到heroku然后清除缓存。我创建了一个deploy.rake文件,就是这样:

namespace :deploy do

    task :production do
        puts "deploying to production"
        system "git push heroku"
        puts "clearing cache"
        system "heroku console Rails.cache.clear"
        puts "done"
    end

end

现在,我只需输入rake deploy:production。

,而不是输入git push heroku

答案 3 :(得分:7)

2013年1月25日:这适用于在Cedar上的Ruby 1.9.3上运行的Rails 3.2.11应用程序

Gemfile添加以下行以强制使用ruby 1.9.3:

ruby '1.9.3'

使用以下内容创建名为lib/tasks/clear_cache.rake的文件:

if Rake::Task.task_defined?("assets:precompile:nondigest")
  Rake::Task["assets:precompile:nondigest"].enhance do
    Rails.cache.clear
  end
else
  Rake::Task["assets:precompile"].enhance do
    # rails 3.1.1 will clear out Rails.application.config if the env vars
    # RAILS_GROUP and RAILS_ENV are not defined. We need to reload the
    # assets environment in this case.
    # Rake::Task["assets:environment"].invoke if Rake::Task.task_defined?("assets:environment")
    Rails.cache.clear
  end
end

最后,我还建议您在应用上运行heroku labs:enable user-env-compile,以便在预编译过程中可以使用其环境。

答案 4 :(得分:2)

除了您在“应用程序启动”上运行的应用程序内部可以执行的操作之外,您可以使用会命中URL的heroku部署挂钩(http://devcenter.heroku.com/articles/deploy-hooks#http_post_hook)在您的应用程序中清除缓存

答案 5 :(得分:0)

我已添加config/initializers/expire_cache.rb

ActionController::Base.expire_page '/'

工作甜蜜!

答案 6 :(得分:0)

由于不推荐使用heroku gem,所以更新版本的Solomons非常优雅的答案是在lib/tasks/heroku_deploy.rake中保存以下代码:

namespace :deploy do
    task :production do
        puts "deploying to production"
        system "git push heroku"
        puts "clearing cache"
        system "heroku run rake cache:clear"
        puts "done"
    end
end

namespace :cache do
  desc "Clears Rails cache"
  task :clear => :environment do
    Rails.cache.clear
  end
end

然后在命令行中键入git push heroku master而不是rake deploy:production。 要清除缓存,您可以运行rake cache:clear

答案 7 :(得分:0)

我喜欢使用的解决方案如下:

首先,我实现了一个deploy_hook操作,该操作查找为每个应用程序设置不同的参数。通常我只是在“home”或“public”控制器上执行此操作,因为它不需要那么多代码。

### routes.rb ###

post 'deploy_hook' => 'home#deploy'

### home_controller.rb ###

def deploy_hook
  Rails.cache.clear if params[:secret] == "a3ad3d3"
end

而且,我只是告诉heroku设置一个部署挂钩,以便在我部署时发布到该操作!

heroku addons:add deployhooks:http \
   --url=http://example.com/deploy_hook?secret=a3ad3d3

现在,每次部署时,heroku都会回复一个HTTP帖子,让我知道部署工作正常。

对我来说就像一个魅力。当然,秘密令牌不是“高安全性”,如果有一个好的攻击向量,如果缓存清除了你的网站,那么就不应该使用它。但是,老实说,如果该网站对攻击至关重要,那么就不要在Heroku上托管它!但是,如果您想稍微增加安全性,那么您可以使用Heroku配置变量,而根本不在源代码中使用“令牌”。

希望人们觉得这很有用。

答案 8 :(得分:0)

我也遇到了这个问题,但是想要坚持使用git部署而不需要额外的脚本作为包装器。

所以我的方法是在slug生成期间使用标记当前预编译的uuid编写文件。这被称为assets:precompile中的一个钩子。

# /lib/tasks/store_asset_cacheversion.rake
# add uuidtools to Gemfile

require "uuidtools"

def storeCacheVersion
  cacheversion = UUIDTools::UUID.random_create
  File.open(".cacheversion", "w") { |file| file.write(cacheversion) }
end

Rake::Task["assets:precompile"].enhance do
  puts "Storing git hash in file for cache invalidation (assets:precompile)\n"
  storeCacheVersion
end

Rake::Task["assets:precompile:nondigest"].enhance do
  puts "Storing git hash in file for cache invalidation (assets:precompile:nondigest)\n"
  storeCacheVersion
end

另一个是初始化程序,它根据缓存版本检查此id。如果它们不同,则会有另一个预编译,并且缓存将失效。

因此,应用程序旋转或关闭的频率或者工作者将分配多少节点无关紧要,因为slug生成只发生一次。

# /config/initializers/00_asset_cache_check.rb

currenthash = File.read ".cacheversion"
cachehash   = Rails.cache.read "cacheversion"

puts "Checking cache version: #{cachehash} against slug version: #{currenthash}\n"

if currenthash != cachehash
  puts "flushing cache\n"
  Rails.cache.clear
  Rails.cache.write "cacheversion", currenthash
else
  puts "cache ok\n"
end

我需要使用随机ID,因为据我所知,无法获取git哈希或任何其他有用的ID。也许是ENV[REQUEST_ID],但这也是一个随机ID。

关于uuid的好处是,它现在也独立于heroku。