Files
2026-09-12 23:12:15 +08:00

233 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 技术选型说明
本章详细阐述系统各技术组件的选型理由、与同类主流方案的对比分析,以及版本约束说明,旨在帮助开发者理解技术选型的依据与权衡,确保团队在技术决策上达成共识,并为后续的技术演进提供参考依据。
## 后端框架选型
### FastAPI
:::tip 为什么选择 FastAPI?
FastAPI 基于 ASGI 原生异步、类型提示驱动的自动文档、Pydantic v2 的高性能校验,使其在构建 RESTful API 时具有显著优势。对于后台管理系统这类以 CRUD 为主的场景,FastAPI 的开发效率和运行性能表现优异。
:::
| 特性 | 说明 |
|:---|:---|
| **原生异步** | 基于 ASGI,`async/await` 一等公民,充分利用 I/O 等待时间 |
| **请求校验** | Pydantic v2 声明式校验,自动 OpenAPI 文档 |
| **自动文档** | 内置 Swagger UI + ReDoc,零配置即用 |
| **类型安全** | 全链路类型提示,IDE 补全完善 |
| **依赖注入** | `Depends` 机制天然适合认证、权限等横切关注点的注入 |
| **高性能** | 基于 Starlette + uvicorn,吞吐量表现优异 |
| **轻量灵活** | 核心概念少,学习曲线平缓 |
### 选择 FastAPI 的核心理由
1. **原生异步**:后台管理系统需要处理并发请求(文件上传、批量操作、定时任务),FastAPI 的原生异步模型能充分利用 I/O 等待时间
2. **Pydantic 校验**:声明式的数据校验 + 自动生成的 API 文档,减少 60% 以上的参数校验代码
3. **SQLAlchemy 解耦**:ORM 不与框架强绑定,支持多数据库驱动切换(MySQL / PostgreSQL / SQL Server / SQLite / Oracle)
4. **依赖注入**:FastAPI 的 `Depends` 机制天然适合认证、权限等横切关注点的注入
5. **性能优势**:在高并发场景下,FastAPI 的吞吐量表现优异
## ORM 选型
### SQLAlchemy 2.0
:::tip 为什么选择 SQLAlchemy?
SQLAlchemy 是 Python 生态中最成熟、功能最完备的 ORM 框架,2.0 版本统一了 Core 和 ORM 的 API 风格,同时保持了对多种数据库方言的原生支持。
:::
| 特性 | 说明 |
|:---|:---|
| **声明式模型** | 基于 `declarative_base()` 定义模型类,字段与数据库列一一映射 |
| **多数据库方言** | 通过 `DB_DRIVER` 切换 MySQL / PostgreSQL / SQL Server / SQLite / Oracle |
| **会话管理** | `SessionLocal` + `contextvars` 实现请求级会话隔离 |
| **连接池** | 内置连接池(`QueuePool`),支持 `DB_POOL_SIZE` / `DB_MAX_OVERFLOW` 配置 |
| **软删除** | 通过 `is_delete` 字段 + Repository 基类自动过滤实现 |
| **事务控制** | 中间件自动 commit/rollback,业务代码无需手动管理 |
版本约束:`SQLAlchemy >= 2.0.51`
## 请求校验选型
### Pydantic v2
| 特性 | 说明 |
|:---|:---|
| **声明式校验** | 通过 `BaseModel` + `Field(...)` 声明字段约束,自动校验 |
| **自定义验证器** | `@field_validator` 支持复杂的业务校验逻辑(如唯一性检查) |
| **自动文档** | 校验规则自动映射到 OpenAPI Schema,Swagger UI 即时展示 |
| **高性能** | v2 核心用 Rust 重写,校验速度较 v1 提升 5-50 倍 |
| **错误聚合** | 全局 `RequestValidationError` 处理器将所有校验错误合并为一条消息 |
版本约束:`pydantic >= 2.13.4`
## 前端技术栈
### Vue3 + Vite + ElementPlus
| 组件 | 版本 | 选型理由 |
|:---|:---|:---|
| **Vue3** | 3.x | Composition API、更好的 TypeScript 支持、Teleport/Suspense 等新特性 |
| **Vite** | 5.x | 极速 HMR、ESM 原生支持、开箱即用的 TypeScript 支持 |
| **ElementPlus** | 2.x | Vue3 生态最成熟的 UI 组件库,企业级后台管理系统首选 |
| **Pinia** | 2.x | Vue3 官方推荐的状态管理方案,替代 Vuex |
| **Vue Router** | 4.x | Vue3 官方路由,支持动态路由、路由守卫 |
| **Axios** | 1.x | HTTP 客户端,支持请求/响应拦截器、取消请求 |
## 缓存与消息中间件
### Redis
:::tip Redis 在中的角色
Redis 在中承担多个关键职责:JWT 令牌黑名单、登录失败锁定、请求限流计数、数据字典缓存、权限缓存等。采用异步客户端(`redis.asyncio`)与 FastAPI 的异步模型无缝集成。
:::
| 用途 | 数据结构 | 过期策略 |
|:---|:---|:---|
| JWT 黑名单 | String | 等于 Token 剩余有效期 |
| 登录失败锁 | String | 指定锁定时长 |
| 滑动窗口限流 | String (Lua) | 2 倍窗口时长 |
| 数据字典缓存 | String (JSON) | TTL 可配置 |
| 权限列表缓存 | String (JSON) | 变更时主动失效 |
版本约束:`redis >= 8.0.1`(async 客户端)
## 定时任务
### APScheduler
| 特性 | 说明 |
|:---|:---|
| **调度策略** | 支持 Cron、Interval、Date 三种触发器 |
| **持久化** | 任务定义存储在数据库,重启后自动恢复 |
| **分布式锁** | 通过 Redis 实现多实例互斥,避免重复执行 |
| **日志记录** | 每次执行记录到 `fastapi_job_log` 表 |
### Cron 表达式格式
项目支持 **5 字段**和 **6 字段**两种 Cron 表达式,6 字段首字段为秒:
| 字段 | 5 字段格式 | 6 字段格式 | 允许值 | 允许的特殊字符 |
|:----|:----|:----|:----|:----|
| 秒 | - | 第 1 位 | 0-59 | `, - * /` |
| 分钟 | 第 1 位 | 第 2 位 | 0-59 | `, - * /` |
| 小时 | 第 2 位 | 第 3 位 | 0-23 | `, - * /` |
| 日 | 第 3 位 | 第 4 位 | 1-31 | `, - * / ? L W` |
| 月 | 第 4 位 | 第 5 位 | 1-12 | `, - * /` |
| 星期 | 第 5 位 | 第 6 位 | 0-7(0 和 7 均为周日) | `, - * / ? L #` |
### 特殊字符说明
| 字符 | 含义 | 示例 |
|:----|:----|:----|
| `*` | 所有值 | `* * * * *` = 每分钟 |
| `?` | 不指定(用于日和星期互斥) | `0 0 0 * * ?` = 每天 0 点,星期不指定 |
| `-` | 范围 | `1-5` = 1 到 5 |
| `,` | 列举 | `1,3,5` = 1、3、5 |
| `/` | 步长 | `*/5` = 每隔 5 个单位 |
| `L` | 最后(Last) | `L` 在日字段 = 月末;`5L` 在星期字段 = 最后一个周五 |
| `W` | 最近工作日(Weekday) | `15W` = 离 15 号最近的工作日 |
| `#` | 第几个星期几 | `6#3` = 第 3 个周五(6=周五) |
### 常用 Cron 表达式示例
**基础频率**
| 表达式 | 说明 |
|:----|:----|
| `* * * * *` | 每分钟执行 |
| `*/5 * * * *` | 每 5 分钟执行 |
| `0 * * * *` | 每小时整点执行 |
| `0 */2 * * *` | 每 2 小时执行 |
| `0 0 * * *` | 每天凌晨 0 点执行 |
| `0 0 */1 * *` | 每天凌晨 0 点(同上) |
**每天定时**
| 表达式 | 说明 |
|:----|:----|
| `0 8 * * *` | 每天早上 8:00 |
| `0 12 * * *` | 每天中午 12:00 |
| `0 18 * * *` | 每天下午 18:00 |
| `0 0 * * *` | 每天凌晨 0:00 |
| `30 9 * * *` | 每天早上 9:30 |
| `0 9,18 * * *` | 每天 9:00 和 18:00(上下班提醒) |
| `0 8-18 * * *` | 每天 8:00 到 18:00 整点(工作时间每小时) |
**每周定时**
| 表达式 | 说明 |
|:----|:----|
| `0 0 * * 0` | 每周日凌晨 0:00 |
| `0 9 * * 1` | 每周一早上 9:00 |
| `0 9 * * 1-5` | 工作日(周一到周五)早上 9:00 |
| `0 9 * * 1,3,5` | 周一、周三、周五早上 9:00 |
| `0 0 * * 6L` | 每月最后一个周六凌晨 0:00 |
**每月定时**
| 表达式 | 说明 |
|:----|:----|
| `0 0 1 * *` | 每月 1 号凌晨 0:00 |
| `0 0 15 * *` | 每月 15 号凌晨 0:00 |
| `0 0 L * *` | 每月最后一天凌晨 0:00 |
| `0 9 1,15 * *` | 每月 1 号和 15 号早上 9:00 |
| `0 0 1 1,4,7,10 *` | 每季度首月 1 号凌晨(季度报表) |
**秒级触发(6 字段)**
| 表达式 | 说明 |
|:----|:----|
| `*/30 * * * * *` | 每 30 秒执行 |
| `0 */5 * * * *` | 每 5 分钟整点执行(等同 5 字段 `*/5 * * * *`) |
| `0 0 9 * * *` | 每天 9:00:00 整秒执行 |
| `0 30 8 * * 1-5` | 工作日 8:30:00 执行 |
| `*/10 * 8-18 * * *` | 工作时间每 10 秒执行(高频监控) |
**业务场景示例**
| 场景 | 表达式 | 说明 |
|:----|:----|:----|
| 数据库备份 | `0 2 * * *` | 每天凌晨 2:00 备份 |
| 日志清理 | `0 3 * * 0` | 每周日凌晨 3:00 清理过期日志 |
| 月度报表 | `0 8 1 * *` | 每月 1 号早上 8:00 生成报表 |
| 心跳检测 | `*/5 * * * *` | 每 5 分钟检测服务状态 |
| 缓存刷新 | `0 */6 * * *` | 每 6 小时刷新一次缓存 |
| 工作日签到提醒 | `0 9 * * 1-5` | 工作日早上 9:00 发送提醒 |
| 订单超时检查 | `*/30 * * * *` | 每 30 秒检查超时未支付订单 |
| 定时推送 | `0 20 * * *` | 每天晚上 8:00 推送消息 |
### 常见错误
| 错误写法 | 问题 | 正确写法 |
|:----|:----|:----|
| `0 0 0 * * * *` | 7 个字段,非法 | `0 0 0 * * *`(6 字段)或 `0 0 * * *`(5 字段) |
| `0 0 * * 7` | 星期 7 超出范围 | `0 0 * * 0`(0 和 7 均为周日,但推荐用 0) |
| `0 0 32 * *` | 日 32 超出范围 | `0 0 1-31 * *` |
| `0 0 * 13 *` | 月 13 超出范围 | `0 0 * 1-12 *` |
| `*/0 * * * *` | 步长不能为 0 | `*/1 * * * *` |
## 其他关键依赖
| 依赖 | 版本 | 用途 |
|:---|:---|:---|
| `uvicorn` | >= 0.51.0 | ASGI 服务器,`src/main.py` 通过 `uvicorn.run(app, ...)` 启动 |
| `PyJWT` | >= 2.13.0 | JWT 令牌签发与验证(HS256 算法),`src/core/jwt.py` |
| `bcrypt` | >= 4.0.0 | 密码哈希(带随机盐),`src/core/password.py` |
| `openpyxl` | >= 3.1.0 | Excel 导入导出,文件上传/下载模块使用 |
| `Pillow` | >= 10.0.0 | 验证码图片生成,`src/utils/captcha/` |
| `python-dotenv` | >= 1.0.0 | `.env` 配置文件加载,`src/core/config/__init__.py` 首先调用 `load_dotenv()` |
| `alembic` | >= 1.13.0 | 数据库迁移,`migrations/` 目录,`scripts/init_db.py` 末尾调用 `alembic stamp head` |
| `APScheduler` | >= 3.10.0 | 定时任务调度,`src/modules/job/scheduler.py`,在 `create_app()` lifespan 中初始化 |
| `bleach` | >= 6.0.0 | 富文本 XSS 清洗,`src/utils/rich_text.py` 的 `sanitize_html()` |
## 版本锁定策略
:::warning 版本管理
所有依赖版本在 `requirements.txt` 中锁定最低版本(`>=x.y.z`),确保兼容性的同时允许安全补丁升级。生产环境建议使用 `pip freeze` 生成精确版本锁文件。
:::
## 总结
项目的技术选型以「高性能、类型安全、可扩展」为核心原则。FastAPI + SQLAlchemy 2.0 + Pydantic v2 构成后端铁三角,Vue3 + Vite + ElementPlus 提供现代化前端体验,Redis 承担缓存与中间件职责。各组件版本经过充分测试验证,形成稳定的技术底座。选型时优先考虑组件的独立性和可替换性,避免强耦合,为未来的架构演进预留空间。