【问题标题】:Clear Memcached on Heroku Deploy在 Heroku Deploy 上清除 Memcached
【发布时间】:2011-12-05 16:30:31
【问题描述】:

当我将 Rails 应用部署到 Heroku 时,自动清除 Memcached 的最佳方法是什么?

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

我想让这完全自动化。我不想在每次部署时都清除 heroku 控制台中的缓存。

谢谢!

【问题讨论】:

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


    【解决方案1】:

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

    在这个脚本中,清除缓存的命令是:

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

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

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

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

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

    【讨论】:

    • 我将其更改为正确答案,因为它目前有效,不像投票最多的答案,它有一个旧的解决方案。
    • 您介意分享那个 bash 脚本吗?我从来没有用过这样的,但现在那将是惊人的。
    • @BlaineHatab 当然,这里是:gist.github.com/fcarrega/9e93ae62a5db6c120e87
    【解决方案2】:

    [在青瓷雪松堆上]

    -- [2012 年 6 月 18 日更新 -- 这不再有效,看看我是否能找到其他解决方法]

    我发现处理这些部署后挂钩的最简洁方法是锁定在 slug 编译期间已调用的 assets:precompile 任务。向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 文件中,它被很好地拾取。

    【讨论】:

    • 希望我可以多次投票,这确实是最干净的方式。
    • 不错的解决方案。但是,我在部署时看不到打印消息。其他人可以确认这是有效的吗?根据stackoverflow.com/questions/9966408/…,它可能不起作用。
    • 我确认这不起作用。 Heroku 运行 assets:precompile:digest,但即使你 enahance 那个任务,它只会导致预编译失败。
    • 自从我最初实现它以来,它已经停止工作。将尝试寻找其他解决方案。
    • @Hollownest,lib/tasks/heroku_deploy.rake 会自动调用吗?
    【解决方案3】:

    我最终做的是创建一个新的 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
    

    现在,我不用输入 git push heroku,而是输入 rake deploy:production。

    【讨论】:

      【解决方案4】:

      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,以便您可以在预编译过程中使用它的环境。

      【讨论】:

      • 这对我有用,但只运行 :nondigest 任务。想知道为什么会生成带有摘要和不带有摘要的资产。
      【解决方案5】:

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

      【讨论】:

      • 我倾向于这个,但想知道 heroku 的部署挂钩有多可靠?它会在失败时重新发送吗?超时多长时间(必须启动测功机才能接收)。
      【解决方案6】:

      我添加了config/initializers/expire_cache.rb

      ActionController::Base.expire_page '/'
      

      工作甜蜜!

      【讨论】:

      • 每次启动 web dyno 时不会清除缓存吗?否则这将是一个不错的干净解决方案。
      • @nruth 我不知道。太糟糕了,我现在无法调查。也许你可以找到它并告诉我们。或者我稍后再做。
      • @nruth 是对的。这会在您的应用程序每次启动时清除您的缓存,这可能比您想象的要多。上面所罗门的回答是最好的方法。
      • @xentek 还有一个问题。当您在一个始终处于清醒状态的工作人员上运行应用程序时,该应用程序是否也会启动很多次?
      • 是的。实际上,您更有可能使用只有一个工作人员的应用程序重新启动您的测功机……如果没有活动的请求,heroku 会让免费应用程序“休眠”,这可能意味着它必须启动您的应用程序在下一个请求。您可以通过每隔几分钟 ping 应用程序来解决此问题。
      【解决方案7】:

      由于 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
      

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

      【讨论】:

        【解决方案8】:

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

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

        ### 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 配置变量,而源代码中根本没有“令牌”。

        希望人们觉得这很有用。

        【讨论】:

          【解决方案9】:

          我也遇到了这个问题,但想坚持使用 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。

          【讨论】:

            猜你喜欢
            • 2012-09-10
            • 2018-09-16
            • 1970-01-01
            • 2012-05-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-21
            • 2012-09-20
            相关资源
            最近更新 更多