在 App Engine 中处理架构迁移
Handling Schema Migrations in App Engine
我在我的一个 App Engine 应用程序中更新了几个经常使用的 NDB 模型,方法是在它们之间移动一些属性。因此,某些模型现在包含我的应用程序的先前版本会在不同位置查找的数据(但无法找到)。我已经更新了我的处理程序,以确保在我 运行 伴随我发布的迁移之后不会发生这种情况。
但是,我担心架构迁移时会发生什么。我已经用几百个实体在本地测试了我的迁移,任务花费了大约 1 秒(使用 deferred 的)。由于我在生产中有超过 1000 个实体,我想这个任务实际上需要几秒钟。与此同时,我确信用户会遇到服务问题。
从其他问题(例如 this one)中,我了解到一个好的做法是将用户重定向到一个页面,提醒他们计划停机进行维护。但是,这对我来说并不是一个真正的选择——我们需要尽可能延长正常运行时间。
因此,我的问题是:有没有办法让我的应用程序保持联机状态并仍然执行可能很长的迁移?我正在考虑使用 App Engine 的 "Traffic Splitting" 在新应用版本迁移时让用户继续使用旧应用版本,但这仍然会导致服务问题。
您可以执行 2 次迁移 (add + delete) 而不是一次 (move) 一个。
第一次迁移只是 添加 要移动到模型中新位置的属性。
更新读取属性的代码以首先检查新位置,如果属性不存在,则回退到旧位置。对于这 2 个位置,查询可能需要加倍,并添加逻辑以识别和跳过重复结果。几乎是新旧代码的结合。
然后您可以更新编写属性的代码以使用新位置。过了这一刻创建的实体将不再有旧位置。如果您想更安全地玩它(能够回滚到旧代码版本)或者如果您想将旧应用程序版本 运行ning 保留一段时间,您可以让编写代码同时使用旧版本和新版本地点。
然后 运行 一项 one-time 作业将属性内容从旧位置(如果存在)复制到新位置。这确保所有属性都存在于所有实体的新位置。
此时您可以删除所有访问旧位置的代码。
这是没有return的要点。在下一步之前,您需要停止任何 GAE 实例 运行 使用您的旧应用程序代码 - 它们将不再 运行 正确,并且您将无法在没有另一个 DB-updating 的情况下回滚您的代码] 工作。
然后 运行 一个 one-time 清理作业,从所有实体的旧位置删除属性 - 最新版本的代码不再访问它们。
完成第二次迁移删除模型中旧位置的属性。
可能需要大量工作,但无论迁移持续多长时间,都应该可以实现零停机时间(对于最新的应用程序版本)。
更新:
中描述了一个可能更好的迁移算法(避免有问题的 OR
' 双重查询)
我在我的一个 App Engine 应用程序中更新了几个经常使用的 NDB 模型,方法是在它们之间移动一些属性。因此,某些模型现在包含我的应用程序的先前版本会在不同位置查找的数据(但无法找到)。我已经更新了我的处理程序,以确保在我 运行 伴随我发布的迁移之后不会发生这种情况。
但是,我担心架构迁移时会发生什么。我已经用几百个实体在本地测试了我的迁移,任务花费了大约 1 秒(使用 deferred 的)。由于我在生产中有超过 1000 个实体,我想这个任务实际上需要几秒钟。与此同时,我确信用户会遇到服务问题。
从其他问题(例如 this one)中,我了解到一个好的做法是将用户重定向到一个页面,提醒他们计划停机进行维护。但是,这对我来说并不是一个真正的选择——我们需要尽可能延长正常运行时间。
因此,我的问题是:有没有办法让我的应用程序保持联机状态并仍然执行可能很长的迁移?我正在考虑使用 App Engine 的 "Traffic Splitting" 在新应用版本迁移时让用户继续使用旧应用版本,但这仍然会导致服务问题。
您可以执行 2 次迁移 (add + delete) 而不是一次 (move) 一个。
第一次迁移只是 添加 要移动到模型中新位置的属性。
更新读取属性的代码以首先检查新位置,如果属性不存在,则回退到旧位置。对于这 2 个位置,查询可能需要加倍,并添加逻辑以识别和跳过重复结果。几乎是新旧代码的结合。
然后您可以更新编写属性的代码以使用新位置。过了这一刻创建的实体将不再有旧位置。如果您想更安全地玩它(能够回滚到旧代码版本)或者如果您想将旧应用程序版本 运行ning 保留一段时间,您可以让编写代码同时使用旧版本和新版本地点。
然后 运行 一项 one-time 作业将属性内容从旧位置(如果存在)复制到新位置。这确保所有属性都存在于所有实体的新位置。
此时您可以删除所有访问旧位置的代码。
这是没有return的要点。在下一步之前,您需要停止任何 GAE 实例 运行 使用您的旧应用程序代码 - 它们将不再 运行 正确,并且您将无法在没有另一个 DB-updating 的情况下回滚您的代码] 工作。
然后 运行 一个 one-time 清理作业,从所有实体的旧位置删除属性 - 最新版本的代码不再访问它们。
完成第二次迁移删除模型中旧位置的属性。
可能需要大量工作,但无论迁移持续多长时间,都应该可以实现零停机时间(对于最新的应用程序版本)。
更新:
OR
' 双重查询)