单体架构详解:Flask/Django单体项目的典型结构、优缺点分析

聊到后端架构,很多人一上来就谈微服务、容器化。但说实话,我做了十几年后端,见过太多项目死在过度设计上。单体架构虽然被吐槽“老土”,但它依然是绝大多数项目的起点,也是你理解更复杂架构的基础。

今天我们就来拆解一下,Flask和Django这两种Python主流框架的单体项目,到底长什么样,有什么坑,又有什么不可替代的优势。

一、Flask单体项目的典型结构

Flask以“微框架”自居,但微不代表弱。我习惯把Flask单体项目组织成下面这样:

my_flask_app/
├── app/
│   ├── __init__.py          # 应用工厂
│   ├── models.py            # 数据模型
│   ├── views.py             # 路由和视图函数
│   ├── forms.py             # 表单处理
│   ├── utils.py             # 工具函数
│   └── templates/           # Jinja2模板
│       ├── base.html
│       └── index.html
├── static/                  # 静态文件
│   ├── css/
│   └── js/
├── config.py                # 配置文件
├── requirements.txt         # 依赖清单
└── run.py                   # 启动入口

这个结构看起来简单,但我在项目中遇到过一个问题:很多人把所有路由都塞进一个views.py里。项目刚开始还好,等路由超过30个,这个文件就变成了“屎山”。

我的建议: 当views.py超过200行,就按业务模块拆分成多个蓝图(Blueprint)。比如 user.py、order.py、product.py,每个蓝图独立管理自己的路由和视图。

二、Django单体项目的典型结构

Django自带“电池”,它的项目结构比Flask更规范。一个标准的Django单体项目长这样:

my_django_project/
├── my_django_project/       # 项目配置目录
│   ├── __init__.py
│   ├── settings.py          # 全局配置
│   ├── urls.py              # 根路由
│   └── wsgi.py              # WSGI入口
├── apps/                    # 应用目录
│   ├── users/
│   │   ├── models.py
│   │   ├── views.py
│   │   ├── urls.py
│   │   └── admin.py
│   ├── orders/
│   │   ├── models.py
│   │   ├── views.py
│   │   └── urls.py
│   └── products/
│       ├── models.py
│       ├── views.py
│       └── urls.py
├── static/
├── media/
├── templates/
├── manage.py
└── requirements.txt

Django的App机制,说白了就是帮你强制做了模块化。每个App都有自己的models、views、urls,天然就是“微内核”的雏形。

嗯,这里要注意:Django的App不是微服务。它们共享同一个数据库连接,同一个进程空间。你想想看,如果users App挂了,整个项目都挂了——这就是单体架构的典型特征。

三、单体架构的优点

为什么我依然推荐中小型项目从单体开始?原因很实在:

优点 说明
开发效率高 一个项目一个仓库,本地调试、热重载都很快。我做过对比,单体项目启动时间通常在1-3秒,微服务光启动就要30秒+
部署简单 一个Docker镜像,一台服务器,搞定。不需要K8s、服务发现、配置中心这些复杂玩意
调试方便 调用链路都在一个进程里,pdb断点一打,从头跟到尾。微服务里跨服务调试,那叫一个痛苦
事务一致性强 所有操作都在同一个数据库连接里,ACID事务天然支持。我曾经在微服务架构里为了一个分布式事务折腾了整整两周
团队沟通成本低 5-10人的团队,大家改同一个代码库,代码review、合并都简单

核心观点: 单体架构不是“落后”,而是“务实”。对于日活10万以下、团队10人以内的项目,单体架构往往是性价比最高的选择。

四、单体架构的缺点

当然,没有银弹。单体架构的缺点也很明显:

  1. 耦合严重:业务模块之间没有物理隔离。比如订单模块的bug可能导致整个用户注册功能不可用。我在一个电商项目里就遇到过,一个支付回调的异常直接拖垮了整个Web服务。
  2. 扩展粒度粗:你只能对整个应用做水平扩展。哪怕只有订单模块是性能瓶颈,你也得把整个项目复制一份。说白了就是“一人感冒,全家吃药”。
  3. 技术栈锁定:一旦选了Flask或Django,整个项目都得用Python。你想在某个模块里用Go或者Rust?对不起,单体架构不支持。
  4. 部署风险高:哪怕只改了一行CSS,你也得重新构建整个项目、重启整个服务。我曾经因为一个静态资源的缓存问题,导致线上服务中断了15分钟。
  5. 团队协作瓶颈:当团队超过15人,代码冲突会变得频繁。每个人都在改同一个models.py,合并代码时那叫一个酸爽。
避坑指南: 我曾经接手过一个Flask单体项目,views.py有8000多行,models.py有3000多行。整个项目没有任何蓝图拆分,所有逻辑都耦合在一起。重构花了整整三个月。所以,哪怕你用单体架构,也一定要做好模块化。

五、什么时候该用单体?什么时候该放弃?

这个问题没有标准答案,但我可以分享一些经验:

  • 适合用单体: 创业初期、内部工具、原型验证、团队小于10人、业务逻辑相对集中
  • 考虑拆分: 团队超过15人、部署频率每天超过10次、某个模块需要独立扩展、需要引入不同技术栈
  • 必须拆分: 某个模块的bug频繁导致全站宕机、数据库连接数达到上限、单个应用启动时间超过5分钟

你想想看,很多大厂早期也是从单体起步的。Instagram早期就是Django单体,直到用户量过亿才开始拆分。所以,别被“微服务”三个字吓到,先把单体做好,比什么都强。

最后说一句:单体架构不是终点,而是起点。理解它的优缺点,你才能在合适的时机做出正确的架构决策。下一章,我们会聊聊如何从单体平滑演进到模块化架构,敬请期待。