您可以在 Internet 上找到许多关于如何首次将 Django 项目部署到生产环境的文章。但是,当你的项目已经上线,在部署过程中,既要保证相关系统的一致性,又要保证产品的连续性,怎么办?
什么是生产?
生产是可供最终用户使用的软件和硬件复合体。它包括安装了稳定软件的服务器、虚拟机和容器。
生产有很多要求。但是,在本文中,我们将重点关注效率和连续性。
效率是产品做它应该做的事情的保证。
连续性是使用本产品时高效工作的保证。
也就是说,如果登录尝试总是返回错误,这就是效率低下。但是,如果用户很少收到这样的错误,那么这就违反了连续性。
初始数据
根据体系结构,在生产中使用多个容器、虚拟机或服务器。
我不考虑只有一个进程在一台生产服务器上工作的情况,因为它类似于通常的开发环境。
制作方案
通常,您最常遇到具有多个容器的方案。它们通过平衡器访问。可能有不止一个平衡器。从容器访问一个数据库,但可能有多个数据库,包括分片和副本。他们还可以访问 Kafka 等代理和其他服务。其他服务也可以以某种方式与后端交换信息。
代码和数据库的同时更改
例如,让我们只考虑对代码和数据库的更改。
可以在代码中进行更改以影响数据库,反之亦然:
- 添加/删除表。
- 添加/删除列。
- 重命名列或表。
- 更改列类型。
- 更改列的属性(索引)(NULL、唯一、默认)。
您还可以添加触发器和函数、更改方案等等。但是,这些示例中显示了将其应用于生产的一般方法。
详细示例
如果你需要在开发环境本地为一个应用程序添加一个模型(表),那么你应该这样做:
- 向 Django 模型添加一个类。
- 调用命令:
python manage.py makemigrations
。 - 然后:
python manage.py migrate
。 - 只有在那之后,重新启动应用程序。
但在生产环境中,有许多应用程序实例、git 和用于运行迁移的单独进程。
您通常无法直接访问 Prod。这很好。例如,流程可能如下所示。
在这样的方案中,首先运行迁移。然后,一个接一个地重新启动 pod。
在这样的架构中,可能总是会出现迁移已经执行,但生产代码没有改变的情况。
然后更换吊舱。有些实例有新代码,有些实例有旧代码。
而且,如果你在pod替换完成的时候再进行迁移,就会出现另一种情况:服务器上的代码更新了,但是数据库没有更新。
这两种情况都暗示了数据库和代码不一致的一段时间。
幸运的是,Django 不会检查一致性。但是,缺少必要的元素会导致异常。
他们是:
- 代码中模型中存在类,但数据库中不存在类
- 代码中类中存在字段,但数据库中不存在
- 代码和数据库中的表名和列名不同
- 代码和表格中不同类型的数据
- 默认值、NULL 和其他差异,如果涉及到使用它们
- 从代码访问时数据库不期望的其他差异
解决方案
需要在更改代码之前执行迁移,这意味着:
- 添加表
- 添加列
- 添加将 NULL 插入字段的功能
需要在更改代码后执行迁移,这意味着:
- 删除表
- 删除列
- 删除将 NULL 插入字段的功能
重命名分几个步骤执行:
- 创建新字段或表
- 添加新旧字段或表的同步
- 必要时复制历史数据
- 开始使用新的字段或表格
- 删除旧字段或表以及同步
这一切看起来很复杂。但是看看上面给出的方案。在多 pod 生产中,在部署期间,总是会发生部分代码使用旧数据库方案而其他部分使用新数据库方案的情况。这可能会导致异常。
因此,处理 Django 模型的基本算法在生产环境中不起作用。根据特定案例中使用的代码架构和 CI/CD 流程,需要分几步部署更改。
但是,在进行更改时,您始终可以根据代码在向数据库发送请求时所期望的内容来指导。除了标准案例,可能还会有各种异常和障碍,需要聪明才智才能找到解决办法。
在接下来的文章中,我将详细描述这里提到的一些案例。