Files
atlas-seller-kit/docs/architecture/technology-and-deployment.md

126 lines
8.5 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.
# 技术栈、异步任务与部署方案
> 状态:已确认。本文定义首期技术选型和环境边界;具体 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 事务中创建业务任务/`operation` 和 `outbox_events`;事务提交后由独立 Dispatcher 投递 BullMQ,避免“数据库已提交但任务未投递”。详见 [`transactional-outbox-and-idempotency.md`](./transactional-outbox-and-idempotency.md)。
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,并在生产前备份和验证回滚方案。
数据库权限分为迁移角色与应用角色:迁移角色拥有表并只在部署迁移时使用;API/Worker 的应用登录角色只获业务表所需的 DML 权限,不拥有表且没有 `BYPASSRLS`。RLS 策略使用每个事务设置的 `app.workspace_id`;业务表启用并强制 RLS。具体初始化和权限清单见 [`database-security.md`](./database-security.md)。
## 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。
## 8. Ozon Seller 浏览器会话边界
一期浏览器插件可以在用户已登录的 `seller.ozon.ru` 标签页内,以同源请求调用已列白名单的四个网页内部接口,保存净化后的观察结果。该模式使用浏览器自动附带的会话 Cookie,但不提取完整 Cookie、不上传、不在 Atlas 保存,也不能交给云端 Worker 执行。
未来若要支持加密保存浏览器 Cookie,必须作为独立的二级实验能力:按门店验证会话归属,使用信封加密和可撤销的专用密钥记录,任务队列仅传密钥记录 ID,并逐接口限制用途。此类 Cookie 会话不替代官方 Seller API 的发布、库存或状态同步凭据。