同一Django项目共享模型与数据库时如何拆分多应用独立部署?
Django单体拆分独立部署落地方案
首先直接给核心结论:两个隔离部署的Django服务共用同一个数据库是完全可行的,这是大量生产环境验证过的拆分过渡方案,成本远低于直接重构完整微服务架构。
方案一:Monorepo 多镜像独立部署(优先选,改造成本<1人日)
你现在的目录结构不需要做大调整,完全不用先拆成多个代码仓库,核心是把公共依赖和不同业务模块的启动逻辑解耦:
- 解决
internal_app依赖core、settings、manage.py的问题:core、全局配置、入口脚本本身就是所有模块的公共依赖,构建镜像时直接把公共部分打入对应镜像即可,不需要做代码复制或者抽RPC服务。 - 改造settings.py的APP加载逻辑,通过环境变量控制当前部署单元加载的业务模块:
import os # 所有部署单元都要加载的公共基础APP INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "core", ] # 按部署角色加载对应业务APP DEPLOY_ROLE = os.getenv("DEPLOY_ROLE", "all") if DEPLOY_ROLE in ("user", "all"): INSTALLED_APPS += ["userapi_1", "userapi_2"] if DEPLOY_ROLE in ("internal", "all"): INSTALLED_APPS += ["insternal_app_1"]
- 路由配置做同样的动态include逻辑,不同角色的服务只挂载自己负责的路由,不会暴露不属于自己的接口。
- 镜像构建用多阶段构建裁剪不需要的代码:比如构建用户侧镜像时,最终镜像只保留core、userapi相关目录、公共配置和入口文件,不打入internal_app的代码;内部工具镜像反向裁剪,避免不需要的代码出现在生产运行环境中。
- K8s侧配置两组独立的Deployment、Service:
- 用户侧服务:设置环境变量
DEPLOY_ROLE=user,按线上用户流量配置副本数、资源配额、公网Ingress,只有用户侧代码变更时才更新这组Pod - 内部工具服务:设置环境变量
DEPLOY_ROLE=internal,配置内网访问控制的Ingress,副本数可以按内部使用需求配置,只有内部工具变更时只更新这组Pod
- 用户侧服务:设置环境变量
- 数据库迁移单独处理:不要配置服务启动时自动执行migrate,单独维护一个K8s Job,每次涉及表结构变更的代码合并后,先执行迁移Job确认表结构更新完成,再发布对应业务模块的服务,避免多服务并发执行迁移导致的数据错误。
这个方案完全不需要做跨服务通信改造,core的模型直接在本地通过ORM调用,没有额外的性能损耗,也不会破坏现有Django的开发习惯,发版流程完全独立,内部工具上线根本不会触碰用户侧的运行实例。
踩坑提示:core应用里只放公共数据模型、通用工具函数,不要放耦合特定业务的逻辑,避免不同服务加载core时出现逻辑冲突。
方案二:公共依赖抽离(适合团队规模扩大后的长期演进)
如果后续用户侧API和内部工具的迭代节奏、团队分工差异越来越大,可以在方案一的基础上做进一步拆分:
- 把core应用打包成独立的Python私有包,上传到团队内部的PyPI源,用户侧服务、内部工具服务都通过依赖声明安装core包,core包的版本单独维护,涉及core的变更发版后,需要升级的服务自行更新依赖版本即可,不需要强制所有服务同步升级。
- 公共配置、启动脚手架可以沉淀成自定义Django项目模板,两个独立服务基于模板初始化,数据库、缓存等公共基础配置统一维护,各服务的业务配置、部署流程完全独立。
- 跨服务的业务交互不要直接操作对方的私有表,通过内部HTTP接口或者轻量RPC调用,避免表结构耦合。
共用数据库的注意事项
多Django服务共用数据库没有架构层面的问题,只要遵守几个规则就不会出故障:
- 明确表所有权:core的公共表所有服务可读,写操作尽量收敛到固定逻辑层;各业务app的私有表只有所属服务有写权限,其他服务最多只读访问,避免多写入点导致的数据冲突
- 所有表结构变更必须做向后兼容:加字段要设置默认值或允许为空,删字段、改字段类型要分多步发布,避免旧版本服务运行时因为表结构不匹配报错
- 迁移操作永远只有一个执行入口,禁止多个服务同时自动执行migrate
不推荐的做法
- 不要一上来就把core拆成独立的微服务,所有模型操作走RPC调用:对于Django这种重度依赖ORM的框架,这种改造会丢失大量ORM的原生能力,排查问题的复杂度陡增,初期投入产出比极低
- 不要为了拆分把core、公共配置复制多份到各个服务代码库,后续公共逻辑变更时很容易出现多份代码不一致的问题
你当前的目录结构已经非常适合做方案一的改造,整个改造过程不需要停服,也不会影响现有业务逻辑。
内容的提问来源于stack exchange,提问作者everspader
相关产品推荐
相关产品推荐

