简体   繁体   English

Azure部署插槽和数据库迁移

[英]Azure deployment slots and database migrations

TLDR: TLDR:

How can an app running in a staging slot know it is in staging and connect to a test database/run migrations on the test database? 如何在临时插槽中运行的应用程序知道它是否正在升级并连接到测试数据库上的测试数据库/运行迁移? And, how can that same app in the staging slot automatically become aware it has been swapped to live production slot and is now responsible for live business operations? 而且,临时插槽中的同一个应用程序如何自动意识到它已被交换到实时生产槽并且现在负责实时业务操作? (So it can switch to using live db, migrate live db etc) (因此它可以切换到使用实时数据库,迁移实时数据库等)

Long version: 长版:

The topic is covered partly by this question: Azure Web App deployment slots with database migration 该主题部分由以下问题涵盖: Azure Web App部署插槽,具有数据库迁移功能

But i didn't really get my answer there.. 但我没有真正得到我的答案..

My app uses FluentMigrator, initiated by an event/code when the app is initialized, to runs database migrations. 我的应用程序使用FluentMigrator,在应用程序初始化时由事件/代码启动,以运行数据库迁移。 MSBuild used to do it, but now I'm fairly certain that it's called programmatically MSBuild曾经这样做,但现在我很确定它是以编程方式调用的

It seems most sensible for: 似乎最明智的是:

  • production to have a slot-based app setting that points the code at the production db 生产有一个基于插槽的应用程序设置,指向生产数据库中的代码
  • staging to have a slot-based app setting that points the code at the staging db 暂存以具有基于插槽的应用程序设置,该设置将代码指向登台数据库

I can't see any other way for production to remain functional while staging is being proven, if staging has migrations that wreck the DB for production's understanding; 如果登台具有破坏数据库以便生产理解的迁移,我看不到任何其他方式让生产保持功能,同时正在证明分段; the two DBs have to be separate 两个DB必须分开

So if the DBs are separate, surely the only (nearly) zero downtime way of switching the world to using the code in the staging slot is if the switch causes the app to reinitialise itself and changes it so it becomes pointing to the production DB, then fluentmigrator (which should also be called again) can apply the same set of migrations to production and the code in staging runs the business on the production db for a while.. 因此,如果数据库是分开的,那么切换世界到使用暂存插槽中的代码的唯一(几乎)零停机方式是,如果交换机导致应用程序重新初始化并更改它以使其指向生产数据库,然后fluentmigrator(也应该再次调用)可以将同一组迁移应用于生产,并且staging中的代码在生产数据库上运行一段时间的业务。

..production codebase is updated and the swap back occurs. ..production codebase已更新,并且发生了回调。 Production code never migrates the production db because it's already updated by the staging code by the time the new version in production fires up 生产代码永远不会迁移生产数据库,因为在生产中的新版本启动时,它已经由暂存代码更新

The only other way I foresee things working out is to have two DBs, two slots, and you never perform a swap; 我预见到的事情唯一的另一种方法是拥有两个DB,两个插槽,而且你永远不会执行交换; you just deploy to staging, it updates the staging DB, you test and prove good, you deploy to production, it updates the produtcion DB, you verify app working.. and the world has suffered a minor amount of downtime while prod was building (or a major amount if the build failed) 您只需部署到暂存,它会更新暂存数据库,您进行测试并证明是好的,您部署到生产中,它会更新产品数据库,验证应用程序正常工作......并且世界在生产时遭受了少量的停机时间(如果构建失败,则为主要数量)

Is there a mechanism for the former? 前者有机制吗? When a swap occurs, how could the app be pointed to a new DB and how could migrations be run again? 当交换发生时,应用程序如何指向新数据库以及如何再次运行迁移?

If the latter is the only way, then deployment slots might as well just be another web app, right? 如果后者是唯一的方式,那么部署插槽也可能只是另一个Web应用程序,对吧? A web app for staging and a web app for prod, to alleviate any confusion slots cause because of how they are represented in the portal.. 用于登台的Web应用程序和用于prod的Web应用程序,以缓解由于它们在门户中的表示方式而导致的任何混淆槽。

It is possible to have a single production database shared by staging and production Azure App Service slots, and still having zero-downtime deployments. 可以通过暂存和生产Azure App Service插槽共享单个生产数据库,并且仍然可以实现零停机时间部署。

To do this, you need to ensure that all your migrations are backwards compatible , such that the current and new versions of the web app can run simultaneously with the same database. 为此,您需要确保所有迁移都向后兼容 ,以便Web应用程序的当前版本和新版本可以与同一数据库同时运行。 This means you can deploy to the staging slot, perform your smoke tests against the production database, then swap the staging slot for the production slot. 这意味着您可以部署到暂存插槽,对生产数据库执行冒烟测试,然后交换生产槽的暂存插槽。

Some rules that allow this to work: 允许此工作的一些规则:

  • New columns should be nullable or have a default value set 新列应该可以为空或设置默认值
  • Columns cannot be dropped 列不能删除
  • Columns cannot be renamed 列无法重命名

When you do need to make a destructive changes, such as dropping a column, you need to have 2 releases: 当您确实需要进行破坏性更改(例如删除列)时,您需要有2个版本:

  1. A release that removes the dependency from the web app 从Web应用程序中删除依赖关系的版本
  2. A release that performs the change to the database schema 一个执行数据库模式更改的发行版

This sounds like a pain, but in practice you probably won't find yourself making destructive changes that often. 这听起来像是痛苦,但在实践中,你可能不会发现自己经常进行破坏性的改变。

I have recently been solving a similar problem. 我最近一直在解决类似的问题。 My situation is easier in the way that I only deploy to content holding databases while the data gathering are standing aside and not being touched (will be challenging once we have to upgrade them). 我的情况更容易,我只部署到持有数据库的内容,而数据收集站在一边而不被触摸(一旦我们必须升级它们将是具有挑战性的)。

However, we came up with a solution that seems to be the best approach to us. 但是,我们想出了一个似乎是我们最好的解决方案。 We do slot deploy while having two sets of dbs in an elastic pool (what causes almost no extra cost for them), while each slot points to one set of dbs. 我们进行插槽部署,同时在弹性池中有两组dbs(几乎没有任何额外成本),而每个插槽指向一组dbs。 When we do a deploy, we update code and the slot related databases, do testing to verify that it all works and then do the swap - the code and the db. 当我们进行部署时,我们更新代码和插槽相关的数据库,进行测试以验证它是否全部工作,然后进行交换 - 代码和数据库。 It means that after the swap the code in the deployment slot goes live and it points to the dbs we have tested towards, while the previously live code and db set is not offline, ready for another deployment. 这意味着在交换之后,部署槽中的代码生效,它指向我们测试过的dbs,而之前的实时代码和数据库集不是脱机的,可以进行另一次部署。

We can afford this comfort because the data in the dbs is purely under our control and therefore we can prevent to write the db between the deployment and the swap. 我们可以提供这种舒适性,因为dbs中的数据完全在我们的控制之下,因此我们可以阻止在部署和交换之间编写数据库。

However, if your db is gathering data from the live application, you might consider to turn the app off for the time you do the upgrade, merge your live data to your staging db, upgrade your staging db (which already includes the latest data) and then do the swap. 但是,如果您的数据库正在从实时应用程序收集数据,您可能会考虑在升级时关闭应用程序,将实时数据合并到暂存数据库,升级暂存数据库(已包含最新数据)然后进行交换。 This seems to me to be the safest approach to prevent data loss. 在我看来,这是防止数据丢失最安全的方法。 You can also migrate your staging db first and then turn the app off and do the data merge into the new schema, depends on the character of your app, without knowing your exact situation to give a generic advice is quite complicated here. 您还可以先迁移暂存数据库,然后关闭应用程序并将数据合并到新模式中,具体取决于应用程序的特性,而不知道您的确切情况,在此处提供通用建议非常复杂。

Hope these ideas helps you at least a bit, if you have figured out some better approach, I'm keen to hear about it. 希望这些想法至少对你有所帮助,如果你已经找到了一些更好的方法,我很想知道它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM