在Heroku上进行零停机热部署

36
推送到Heroku的一个不好的方面是,我必须在运行数据库迁移之前推送代码(服务器会自动重新启动)。显然,这可能会导致一些500错误,因为用户浏览网站时使用了新代码而没有新的表/属性:Heroku提出的解决方案是使用维护模式,但我希望有一种没有副作用的方式让我的Web应用程序始终运行!有办法吗?例如使用Capistrano:
  • 我准备一个新目录用于部署代码
  • 我运行(反向)迁移,并且旧代码仍然可以工作得很完美
  • 我将Mongrel实例切换到新目录并重新启动服务器
...这样我就没有停机时间了!
7个回答

22
您可以设置第二个Heroku应用程序,该应用程序指向与您的主生产应用程序相同的数据库,并使用辅助应用程序运行DB迁移,而不会中断生产(假设迁移不会破坏您的应用程序的先前版本)。
让我们称Heroku应用程序为PRODUCTIONSTAGING
您的部署顺序将变成以下内容:
1. 将新代码部署到 STAGING
git push heroku staging 2. 在 STAGING 上运行数据库迁移(以更新PROD db)
heroku run -a staging-app rake db: migrate 3. 将新代码部署到 PRODUCTION
git push heroku production 由于您无需超出Heroku的免费套餐范围,因此分期付款应用程序将不会花费您任何费用。而且,设置rake部署脚本来自动完成这项任务也相当简单。
祝您好运!

我相信Heroku会保留您的旧dynos,直到新slug的编译完成,因此在第三步运行时,您的站点应该仍然可用。我想在Heroku将路由从旧dynos切换到新dynos时可能会有一些短暂的停机时间,但应该非常少。 - jshkol
6
如果您真的将其用作分段环境,那么我不确定将您的分段环境链接到生产数据库是否是一个真正好的想法。 - Daniel
STAGING只是一个示例名称,我并不建议您重复使用用于测试预生产代码的相同环境来实现此目的。那样做是不明智的。在这种情况下,您需要创建一个专门用于部署过程的生产应用程序配置的第二个副本。您可以随意命名它。 - jshkol

12

5
唯一改善这个过程的方法是这位先生所建议的。 然而,这仍然不是热部署场景:http://casperfabricius.com/site/2009/09/20/manage-and-rollback-heroku-deployments-capistrano-style/。 我建议的一件事是先将迁移文件推送到Heroku并在推送代码库之前运行它们。 这需要将迁移作为独立提交进行提交,并每次手动推送它们(这并不理想)。 我非常惊讶,现在所有托管在Heroku上的大型应用程序都没有更好的解决此问题的方法。

3

2

我首先提交迁移,运行它们,然后推送其余的代码。像这样添加一个单独的文件:

git commit -m 'added migration' -- db/migrate/2012-your-migration.rb

0

目前我看不到任何在没有停机的情况下完成这个任务的可能性。我也很讨厌这种情况。

这个控制台命令可以在最短的时间内完成。

git push heroku master && 
heroku maintenance:on && 
sleep 5 && 
heroku run rails db:migrate && 
sleep 3 && 
heroku ps:restart && 
heroku maintenance:off
  1. 使用git push heroku master将主分支推送到heroku
  2. 使用heroku maintenance:on进行维护,以避免出现500错误
  3. 使用sleep 5让dynos启动新代码(否则迁移可能会失败)
  4. 使用heroku run rails db:migrate进行实际迁移
  5. 使用heroku ps:restart重新启动确保新的dynos具有最新的模式
  6. 使用heroku maintenance:off关闭维护

如果您有多个应用程序,则可能需要在所有heroku命令后面添加-a <app name>

只需一个命令即可在Mac OSX终端上按顺序运行这些命令。


0

Heroku 无法通过 capistrano 进行部署。您被 Heroku 发布的工具所阻止。

在所有情况下都不可能实现零停机系统。如何在进行大规模更改时改变架构而不停止服务器。如果您不停止它,则可以避免某些更改,但您的数据库可能会不一致。因此,使用维护页面是一种常规解决方案。

如果您想要一个小型解决方案来避免问题,则可以在两个服务器之间进行平衡。其中一个只读取数据库,以便在迁移期间切换到此实例,从而避免维护页面。完成迁移后,您可以返回到主服务器。


1
嗨,shingara, 很抱歉,我不同意你的看法。我不想为此使用负载均衡:Heroku 的一个伟大特点是通过必要性实现“透明”的云能力,我想利用这个特点...在 Heroku 中进行负载均衡需要维护两个不同的应用程序,只读数据库可能会给我的用户带来问题。而且,没有停机时间的系统并非不可能。我正在正确地使用所解释的系统,如果出现无法向后兼容的 db 模式的重大更改,我可以使用维护页面:但这只占我所有情况的 5%... - zetarun
您可以通过使用CouchDB来避免本答案中描述的问题。 - iconoclast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接