# 技术栈、异步任务与部署方案 > 状态:已确认。本文定义首期技术选型和环境边界;具体 Docker Compose、CI/CD、密钥和云资源参数在实施前补充为运行手册。 ## 1. 已确认技术选型 | 层级 | 选型 | 职责 | |---|---|---| | 前端 | React 19、TypeScript、Vite、Ant Design、React Router、Axios | 延续 `ozon-seller-kit/studio` 的前端技术路线,构建卖家工作台。 | | 主后端 | NestJS、TypeScript | 认证、门店、商品/SKU、定价、平台适配、任务编排和 HTTP API。 | | 关系数据库 | PostgreSQL | 业务事实来源:用户、隐藏工作空间、门店、商品、报价、任务记录和审计。 | | 缓存与队列 | Redis、BullMQ | 待执行任务、延迟/重试、进度和限流;不作为业务事实来源。 | | 对象存储(本地) | MinIO | 本地开发存放图片和文件,使用 S3 兼容接口。 | | 对象存储(生产) | 七牛云 Kodo | 生产及共享测试环境存放图片和文件。Kodo 的基础 S3 兼容能力用于上传、下载、删除和短时访问链接。 | | 运行与编排 | Docker、Docker Compose | 本地一键启动依赖;首期服务器部署 API、Worker、Redis 和反向代理。 | 不将旧项目的 FastAPI 服务作为新项目运行时依赖;旧项目的 Ozon 资料、计价规则、采集经验和前端技术路线可作为参考或选择性复用。 ## 2. 服务边界 ```text Browser │ HTTPS ▼ Reverse proxy / CDN ├─ Web:Vite 构建的静态前端 └─ NestJS API ├─ PostgreSQL:业务数据、任务状态、审计与规则快照 ├─ Redis:BullMQ 队列与短期缓存 ├─ Kodo / MinIO:原图、处理图、AI 图和导入文件 └─ BullMQ Worker:水印、AI、平台同步、上架与重试 ``` API 进程只处理短请求、鉴权、事务和任务投递。耗时或会失败重试的工作必须由独立 Worker 执行,不能在 HTTP 请求内直接完成。 ## 3. Redis 与 BullMQ 的使用规则 Redis 是高速的临时基础设施;BullMQ 使用 Redis 保存队列中的任务及其调度/重试信息。两者都不是商品、门店或任务最终结果的唯一存储位置。 | 任务 | API 的动作 | Worker 的动作 | PostgreSQL 应保存的内容 | |---|---|---|---| | 水印/图片处理 | 创建任务并投递队列 | 读取原图、处理、上传派生图 | 任务状态、输入图片、输出图片、错误、重试次数 | | AI 生图/智能规划 | 创建任务并投递队列 | 调用模型、轮询或处理回调、保存结果 | 模型/提示词版本、输入、结果、费用/用量、人工确认状态 | | Ozon 同步 | 创建同步任务 | 限速调用 API,分页拉取并更新数据 | 同步游标、开始/完成时间、错误和结果摘要 | | SKU 发布 | 创建发布任务 | 按店铺限流发布、查询结果、失败重试 | 发布状态、平台任务 ID、请求/响应摘要和错误 | 实现要求: 1. 所有长任务先在 PostgreSQL 创建任务记录,再在事务提交后投递队列;后续实施时使用 outbox 模式避免“数据库已提交但任务未投递”的遗漏。 2. 任务必须幂等:相同 SKU 的一次发布任务重试,不得重复创建平台商品。 3. 重试必须有次数上限、指数退避和可见错误;Ozon 等第三方 API 需按店铺/API 限额控制并发。 4. Redis 可丢失或重建,Worker 应能根据 PostgreSQL 中的未完成任务恢复投递;业务结果不只存在于 Redis。 ## 4. 对象存储策略 对象存储保存二进制文件;PostgreSQL 只保存对象键、文件哈希、MIME 类型、尺寸、归属关系和处理状态,不保存大图片的二进制内容。 ### 4.1 概念 - **Bucket(存储桶)**:一个独立文件仓库,例如 `atlas-prod-assets`。 - **Object Key(对象键)**:桶内文件的唯一键,例如 `workspaces/{workspaceId}/products/{productId}/original/{assetId}.jpg`。 - **S3 兼容**:以 Bucket、Object Key、上传/下载/删除和预签名 URL 这一类通用 API 操作对象存储。MinIO 与七牛 Kodo 均可用于此模式;应用只依赖首期所需的基础能力。 ### 4.2 文件分层与访问控制 建议对象键按业务归属分层: ```text workspaces/{workspaceId}/ watermarks/{assetId}/ products/{productId}/original/{assetId} products/{productId}/processed/{assetId} products/{productId}/ai-generated/{assetId} imports/{taskId}/{filename} ``` 规则: 1. Bucket 默认私有;用户原图、模板图、导入文件和 AI 结果不长期公开。 2. 前端上传使用服务端签发的短时上传凭证或预签名 URL;浏览器不保存永久 Kodo 密钥。 3. 前端预览/下载使用短时访问 URL,或由 API 受控转发。 4. Ozon 发布由 Worker 用受控服务端凭据读取文件;不因平台发布而把私有原图改为公共读。 5. 对象删除应先检查数据库引用;商品、水印软删除或保留期结束后,由后台清理任务物理删除。 ### 4.3 本地、测试与生产 | 环境 | 对象存储 | 说明 | |---|---|---| | local | Docker 中的 MinIO | 每位开发者独立数据,可随时用种子数据重建。 | | staging | 七牛 Kodo 独立 Bucket | 家/公司联调和验收使用,严禁与生产 Bucket 混用。 | | production | 七牛 Kodo 独立 Bucket | 保存真实用户文件,凭据只在生产运行环境中配置。 | 首期不在普通单台云服务器自建生产 MinIO:自行承担磁盘冗余、备份、故障恢复、TLS、升级和监控,不能因“部署了 MinIO”而获得托管对象存储的可靠性。 ## 5. 环境与数据库策略 | 环境 | PostgreSQL | 目的 | |---|---|---| | local | 本机 Docker PostgreSQL | 日常开发、迁移编写和自动化测试;每位开发者独立。 | | staging | 云端独立 PostgreSQL | 家/公司共同联调、演示和测试店铺验证。 | | production | 云托管 PostgreSQL | 真实业务数据;仅生产服务通过私网或受控网络访问。 | 不能把生产数据库作为开发数据库,也不建议所有日常开发直接共用同一云端数据库。数据库结构通过迁移文件保持一致;演示数据通过版本化 seed 脚本保持一致。迁移顺序必须是 local → staging → production,并在生产前备份和验证回滚方案。 ## 6. AI 能力边界 首期 AI 智能规划、文案和生图均通过 Provider Adapter 调用云模型 API。NestJS 负责权限、上下文组装、结构化结果校验、任务状态和人工确认;模型不得直接改价、发布或修改门店数据。 若未来出现 GPU 推理、自托管扩散模型、大规模 OCR/CV、训练或微调,再增加独立 Python AI Worker。Python Worker 通过队列或内部 API 接收任务,主业务后端仍保持 NestJS,避免过早维护双语言的主业务系统。 ## 7. Docker 与首期部署 本地 Docker Compose 至少编排:`web`、`api`、`worker`、`postgres`、`redis`、`minio`。前端开发也可单独使用 Vite 热更新,并将 `/api` 代理至本地 API。 首期云端 Docker Compose 编排:`api`、`worker`、`redis`、`reverse-proxy`;PostgreSQL 使用云托管实例,图片使用七牛 Kodo。每个环境使用独立 `.env`/密钥管理配置,密钥不提交 Git、不进入前端构建产物和日志。 在规模、可用性或多机部署出现明确瓶颈前,不引入 Kubernetes。