Capistrano 部署 Rails 应用程序 - 如何处理长时间迁移?

Posted

技术标签:

【中文标题】Capistrano 部署 Rails 应用程序 - 如何处理长时间迁移?【英文标题】:Capistrano to deploy rails application - how to handle long migrations? 【发布时间】:2011-01-15 16:49:09 【问题描述】:

所以我正在使用 Capistrano 将 Rails 应用程序部署到我的生产服务器(apache+passenger),目前部署通常是这样的:

$cap deploy
$cap deploy:migrations

这让我想知道,假设我的 db:migrations 需要很长时间才能在生产服务器上执行(对 db 架构进行了很大的重构)——在这种情况下,Capistrano 的最佳实践是什么?如果用户在部署时连接到我的应用程序会发生什么?我应该在更新数据库时优雅地将用户发送到静态占位符页面吗? Capistrano 会自动处理这个问题吗?我需要编写一个食谱来帮助解决这个问题吗?或者rails/passenger的内部机制是否意味着我完全不必担心这种特殊情况?

谢谢。

【问题讨论】:

【参考方案1】:

如果应用程序暂时不可用,您应该建立一个维护页面。我使用这个 Capistrano 任务:

namespace :deploy do
  namespace :web do
    desc <<-DESC
      Present a maintenance page to visitors. Disables your application's web \
      interface by writing a "maintenance.html" file to each web server. The \
      servers must be configured to detect the presence of this file, and if \
      it is present, always display it instead of performing the request.

      By default, the maintenance page will just say the site is down for \
      "maintenance", and will be back "shortly", but you can customize the \
      page by specifying the REASON and UNTIL environment variables:

        $ cap deploy:web:disable \\
              REASON="a hardware upgrade" \\
              UNTIL="12pm Central Time"

      Further customization will require that you write your own task.
    DESC
    task :disable, :roles => :web do
      require 'erb'
      on_rollback  run "rm #shared_path/system/maintenance.html" 

      reason = ENV['REASON']
      deadline = ENV['UNTIL']      
      template = File.read('app/views/admin/maintenance.html.erb')
      page = ERB.new(template).result(binding)

      put page, "#shared_path/system/maintenance.html", :mode => 0644
    end
  end
end

app/views/admin/maintenance.html.erb 文件应包含:

<p>We’re currently offline for <%= reason ? reason : 'maintenance' %> as of <%= Time.now.utc.strftime('%H:%M %Z') %>.</p>
<p>Sorry for the inconvenience. We’ll be back <%= deadline ? "by #deadline" : 'shortly' %>.</p>

最后一步是使用一些指令配置 Apache 虚拟主机以查找 maintenance.html 文件并将所有请求重定向到它(如果存在):

<IfModule mod_rewrite.c>
  RewriteEngine On

  # Redirect all requests to the maintenance page if present
  RewriteCond %REQUEST_URI !\.(css|gif|jpg|png)$
  RewriteCond %DOCUMENT_ROOT/system/maintenance.html -f
  RewriteCond %SCRIPT_FILENAME !maintenance.html
  RewriteRule ^.*$ /system/maintenance.html [L]
</IfModule>

要将应用程序置于维护模式,请运行 cap deploy:web:disable 并使其再次运行 cap deploy:web:enable

【讨论】:

维护页面会提供“200 OK”还是“503 Service Temporarily Unavailable”? Google 可能会认为,如果您提供 200 OK,您的宝贵内容可能会消失。见googlewebmastercentral.blogspot.com/2011/01/… 好点,Capistrano 本身建议 .htaccess 使用以下 sn-p:gist.github.com/1292705 您忘记了enable 任务! @Jay Levitt enable 任务内置于 Capistrano 本身,因此无需显式指定它,除非覆盖它。【参考方案2】:

我的生产部署通常遵循这个过程:

    cap production deploy:web:disable 将所有请求定向到静态维护页面 cap production deploy 迁移等,分别测试每个服务器以确保一切正常 cap production deploy:web:enable 使网站正常运行

John Topley 的回复在这里为您提供了一些很好的深入信息。

【讨论】:

以上是关于Capistrano 部署 Rails 应用程序 - 如何处理长时间迁移?的主要内容,如果未能解决你的问题,请参考以下文章

rails 4.1 无法通过 capistrano 3 部署

使用 Capistrano 部署 Rails 5.1 / Webpacker 应用程序

Rails 4 + Capistrano + AWS Net::SSH::AuthenticationFailed: 部署

Rails Ubuntu / passenger / capistrano应用程序资产未部署

使用 Capistrano 将 Rails 应用程序部署到多个服务器 - 最佳实践

如何在通过 Capistrano 部署 Rails 应用程序时输入 ssh 密钥的密码?