外观
架构设计与启动过程
架构设计
分层与模块化架构
后端代码集中在 backend/app/ 下,整体分为三块:
api/:业务实现层,按子系统拆分为module_system、module_infra、module_ai、module_bpm四大模块,分别对应系统管理、基础设施、AI 大模型、BPM 工作流。framework/:框架能力层,与具体业务无关,沉淀可复用的基础设施,如database、web、security、common、file、websocket等。config/:配置层,集中管理环境配置、路径锚点和全局常量。
api/ 下所有业务模块统一挂载在版本前缀 v1 中,由顶层 main.py 聚合后通过 FastAPI 的 root_path(/api/v1)对外暴露。四大模块彼此独立,仅在需要时通过 framework 复用能力,避免业务耦合。
业务模块的分层文件职责
每个业务域(如 user、role、dict)都是一个独立目录,内部遵循统一的分层约定,包含以下文件:
| 文件 | 职责 | 说明 |
|---|---|---|
controller.py | 路由与接口层 | 定义 APIRouter、请求/响应模型绑定、权限声明,调用 service 并返回统一响应。 |
service.py | 业务逻辑层 | 承载核心业务逻辑(校验、编排、跨表操作、导入导出等),调用 crud 完成数据访问。 |
crud.py | 数据访问层 | 继承框架 CRUDBase,封装针对本模型的数据库增删改查与复杂查询。 |
model.py | 数据模型层 | 定义 SQLAlchemy ORM 模型,借助 ModelMixin 等基类自动带出公共字段与元数据。 |
schema.py | 数据契约层 | 定义 Pydantic 模型,用于请求体校验、响应序列化与查询参数声明。 |
__init__.py | 包标识 | 维持包结构。 |
一次典型请求会从上往下穿过各层,再逐层返回:
这种分层让"接口定义、业务规则、数据操作"各司其职:新增功能时通常从 schema 定义契约,在 controller 声明路由,在 service 编写逻辑,必要时扩展 crud 与 model。
命名约定
为保证可读性,项目在全链路使用一致的命名:
- 模块目录:以
module_前缀区分子系统,如module_system、module_ai。 - 业务域目录:使用小写下划线,如
user、role、dict。 - 类命名:每个分层文件内主类采用
领域 + 层的命名,例如UserRouter、UserService、UserCRUD、UserModel、UserOutSchema,便于在代码中通过类名即可判断其所属层。 - 路由聚合:每个模块的
router.py收集本模块下所有controller的路由,再以APIRouter(prefix="/xxx")挂载到顶层应用。
启动过程
应用启动流程
应用的入口是 backend/main.py,它基于 typer 提供命令行工具,核心命令有:
python main.py start --env dev:启动 FastAPI 服务(dev 环境自动开启热重载)。python main.py revision --env dev:生成 Alembic 迁移脚本。python main.py upgrade --env dev:执行数据库迁移到最新版本。
启动的关键在于:环境变量 ENVIRONMENT 必须在导入 settings 之前设置,以决定加载哪份环境配置。随后 create_app() 完成应用对象的构建:
启动后的生命周期(lifespan)由 app/app_init.py 管理,分为"启动期"与"关闭期"两段:
- 启动期:依次加载全局事件(如建立 Redis 连接)、预热系统参数缓存、预热数据字典缓存、初始化定时任务调度器、初始化 HTTP 缓存与请求限流器,最后打印启动横幅。
- 关闭期:反向释放资源,关闭调度器、清理缓存、卸载全局事件、释放数据库引擎连接池。
任意一步初始化失败都会直接中断并以非零状态退出,避免带病运行。app_init.py 同时定义了中间件的注册(按声明顺序)、静态文件挂载以及 Swagger/ReDoc 文档入口的重置(当配置中关闭文档时一并关闭 OpenAPI Schema,避免接口结构泄露)。
后端配置
配置由 app/config/settings.py 中的 Settings 类承载,基于 pydantic-settings 实现。加载规则如下:
- 根据环境变量
ENVIRONMENT(dev或prod)读取对应的.env.dev/.env.prod文件(位于backend/env/)。 - 通过
lru_cache缓存单例settings,全项目统一引用,避免重复解析。 - 区分大小写,文件中未出现的项使用类内默认值。
配置按主题分组,覆盖服务器、API 文档、数据库、Redis、日志、跨域、登录认证、验证码、第三方 OAuth、WebSocket、Gzip、文件上传、请求限流等。其中几类以 @property 形式提供的"动态配置"尤其关键:
MIDDLEWARE_LIST:根据开关(如GZIP_ENABLE、CORS_ORIGIN_ENABLE)动态决定是否挂载对应中间件。EVENT_LIST:根据REDIS_ENABLE等开关决定启动时加载哪些全局事件模块。ASYNC_DB_URI/DB_URI:根据DATABASE_TYPE(mysql / postgres )拼接同步与异步连接串。FASTAPI_CONFIG:组装 FastAPI 实例化参数(标题、版本、文档开关、统一响应状态码等)。
前端配置
后端通过以下配置与前端协同,部署时需前后端对齐:
ROOT_PATH = "/api/v1":所有 API 的统一前缀,前端请求基地址应指向该路径。CORS_ORIGIN_ENABLE及ALLOW_ORIGINS/ALLOW_METHODS/ALLOW_HEADERS:控制跨域,开发环境常设为放行,生产环境应缩窄到具体域名。DOCS_URL/REDOC_URL:API 文档入口(如/docs、/redoc),生产环境建议置空关闭。
后端以 /api/v1 作为统一路由前缀,并依赖 CORS 配置允许前端跨域访问;文档入口、演示模式、跨域白名单等开关均可在对应环境的 .env 文件中调整。
事件机制
"全局事件"是一组在应用启动/关闭时被统一调用的初始化函数,由 settings.EVENT_LIST 声明、通过 framework/util/import_util.py 的 import_modules_async 动态导入并执行。以 Redis 为例:
机制要点:
- 事件函数统一接收
app与status两个参数,status=True表示启动、False表示关闭,同一函数据此双向处理资源。 - 初始化结果挂载在
app.state上(如app.state.redis),后续各层通过依赖注入或app.state直接取用,无需自行建立连接。 - 通过往
EVENT_LIST追加可导入的路径字符串即可扩展新的全局事件,框架会在生命周期内自动调用,无需改动app_init主体代码。