# AI临床研究平台 - 阿里云部署架构总览
> **文档版本:** v1.0
> **创建日期:** 2025-12-14
> **目标环境:** 阿里云 SAE + RDS PostgreSQL 15 + OSS
> **架构类型:** 云原生 Serverless + 容器化微服务
> **适用团队:** 1-2人初创团队 → 10人成长团队
---
## 📋 目录
1. [架构全景图](#架构全景图)
2. [5个核心模块关系](#5个核心模块关系)
3. [模块与阿里云服务映射](#模块与阿里云服务映射)
4. [开发环境与部署环境](#开发环境与部署环境)
5. [Docker版本管理策略](#docker版本管理策略)
6. [线上故障快速修复](#线上故障快速修复)
7. [部署文档导航](#部署文档导航)
---
## 架构全景图
### 1. 逻辑架构(用户视角)
```
┌─────────────────────────────────────────────────────────────────────┐
│ 用户浏览器(Browser) │
│ https://your-domain.com │
└────────────────────────────────┬────────────────────────────────────┘
│
┌────────────▼───────────────┐
│ 前端 SPA (React 19) │
│ - 用户界面 │
│ - 路由管理 │
│ - API调用 │
└────────────┬───────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
┌─────────▼──────┐ ┌───────▼───────┐ ┌──────▼──────────┐
│ Node.js后端 │ │ Python微服务 │ │ Dify RAG平台 │
│ (Fastify) │ │ (FastAPI) │ │ (知识库检索) │
│ │ │ │ │ │
│ - 业务逻辑 │ │ - PDF解析 │ │ - 文档上传 │
│ - 权限控制 │ │ - 数据清洗 │ │ - 向量检索 │
│ - API聚合 │ │ - 文件提取 │ │ - LLM对话 │
└────────┬───────┘ └───────┬───────┘ └──────┬──────────┘
│ │ │
│ │ │
└──────────────────┼──────────────────┘
│
┌───────────▼────────────┐
│ PostgreSQL 15 数据库 │
│ (RDS) │
│ │
│ - 10个Schema隔离 │
│ - pg-boss任务队列 │
│ - Postgres-Only架构 │
└────────────────────────┘
```
### 2. 物理架构(阿里云资源)
```
┌───────────────────────────────────────────────────────────────────────────┐
│ 阿里云 VPC(专有网络) │
│ 172.16.0.0/12(内网隔离) │
├───────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SAE (Serverless Application Engine) │ │
│ │ 容器化应用部署平台 │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────────┐ │ │
│ │ │ 前端Nginx │ │ Node.js后端 │ │ Python微服务 │ │ │
│ │ │ 容器应用 │ │ 容器应用 │ │ 容器应用 │ │ │
│ │ ├───────────────┤ ├───────────────┤ ├──────────────────┤ │ │
│ │ │ Nginx 1.25 │ │ Node.js 22 │ │ Python 3.11 │ │ │
│ │ │ React构建产物 │ │ Fastify 5 │ │ FastAPI 0.104 │ │ │
│ │ │ 健康检查/路由 │ │ Prisma 6 │ │ PyMuPDF/Polars │ │ │
│ │ └───────┬───────┘ └───────┬───────┘ └────────┬─────────┘ │ │
│ │ │ │ │ │ │
│ │ │ 内网调用 │ 内网调用 │ │ │
│ │ └──────────────────┴───────────────────┘ │ │
│ │ │ │ │
│ └─────────────────────────────┼─────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ⭐ NAT网关 + EIP(公网出口,必需) │ │
│ ├──────────────────────────────────────────────────────────┤ │
│ │ - 为SAE提供公网访问能力 │ │
│ │ - 后端调用DeepSeek/OpenAI API │ │
│ │ - Python下载公网PDF │ │
│ │ - npm install公网依赖 │ │
│ │ - 成本:NAT网关¥60/月 + EIP流量费 │ │
│ │ - ⚠️ 没有NAT网关,AI功能全部超时! │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────▼──────────────────────────┐ │
│ │ RDS PostgreSQL 15(云数据库) │ │
│ │ rds.pg.s2.large (2核4GB) │ │
│ ├────────────────────────────────────────────────────────┤ │
│ │ - 数据库名:ai_clinical_research │ │
│ │ - 用户:aiclinical_rw(应用专用账号) │ │
│ │ - 内网地址:rm-xxxxx.pg.rds.aliyuncs.com:5432 │ │
│ │ - 自动备份:每天凌晨2点 + 日志备份(PITR) │ │
│ │ - 白名单:172.16.0.0/12(SAE的VPC网段) │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ OSS (Object Storage Service) 对象存储 │ │
│ │ Bucket: aiclinical-data-prod │ │
│ ├──────────────────────────────────────────────────────────┤ │
│ │ - 用户上传文件(PDF、Word、Excel) │ │
│ │ - 文献数据(ASL模块) │ │
│ │ - 数据清洗结果(DC模块) │ │
│ │ - 数据库备份归档(可选) │ │
│ │ - 访问方式:SDK(内网免流量费) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────────┐
│ 独立 ECS 服务器(Dify部署) │
│ ecs.c6.xlarge (4核8GB) │
├───────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Dify RAG 平台 (Docker Compose) │ │
│ ├──────────────────────────────────────────────────────────────┤ │
│ │ - Dify API (dify/api:0.6.13) │ │
│ │ - Dify Web (dify/web:0.6.13) │ │
│ │ - PostgreSQL 15 (postgres:15-alpine,Dify专用数据库) │ │
│ │ - Redis (redis:6-alpine,Dify缓存) │ │
│ │ - Weaviate (向量数据库) │ │
│ │ - Nginx (路由层,处理CORS) │ │
│ │ - Sandbox (代码执行沙箱) │ │
│ │ │ │
│ │ 内网地址:http://172.16.x.x(通过VPC与SAE互联) │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────────┘
```
### 3. 数据流向图
```
用户上传文件
│
├──► 前端 (React)
│ │
│ ├──► /api/v1/pkb/documents (上传到知识库)
│ │ │
│ │ ├──► Node.js后端
│ │ │ │
│ │ │ ├──► OSS (存储原始文件)
│ │ │ └──► Dify API (创建文档向量)
│ │ │ │
│ │ │ └──► Weaviate (存储向量)
│ │ │
│ │ └──► RDS (存储元数据)
│ │
│ ├──► /api/v1/asl/literatures (文献筛选)
│ │ │
│ │ ├──► Node.js后端
│ │ │ │
│ │ │ ├──► Python微服务 (PDF解析)
│ │ │ │ │
│ │ │ │ └──► OSS (读取PDF)
│ │ │ │
│ │ │ └──► RDS (存储文献数据)
│ │ │
│ │ └──► 返回解析结果
│ │
│ └──► /api/v1/dc/extraction (数据清洗)
│ │
│ ├──► Node.js后端
│ │ │
│ │ ├──► Python微服务 (Polars数据处理)
│ │ │ │
│ │ │ └──► OSS (读取Excel/CSV)
│ │ │
│ │ └──► RDS (存储清洗结果)
│ │
│ └──► 返回清洗结果
│
└──► 展示结果
```
---
## 5个核心模块关系
### 1. 模块依赖关系图
```
┌─────────────────────────────────────────────────────────────────┐
│ 核心依赖层级 (从下到上) │
└─────────────────────────────────────────────────────────────────┘
L4: 用户界面层
┌──────────────────────────────────────────────────────┐
│ 前端 (React 19 + Vite 7) │
│ - 调用 Node.js后端的 REST API │
│ - 不直接调用 Python微服务和Dify │
│ - 通过反向代理 (/api/) 路由到后端 │
└──────────────────────────────────────────────────────┘
▲
│ HTTP/HTTPS
│
─────────────────────────────────────────────────────────
L3: 业务逻辑层
┌──────────────────────────────────────────────────────┐
│ Node.js 后端 (Fastify + Prisma) │
│ - 业务逻辑聚合 │
│ - 权限控制 │
│ - 调用 Python微服务 (内网HTTP) │
│ - 调用 Dify API (内网HTTP) │
│ - 数据库访问 (Prisma ORM) │
└──────────────────────────────────────────────────────┘
▲ ▲ ▲
│ │ │
│ (内网) │ (内网) │ (Prisma)
│ │ │
┌──────┴────────┐ ┌──────┴──────┐ ┌────▼──────┐
│ Python微服务 │ │ Dify平台 │ │ PostgreSQL│
└───────────────┘ └─────────────┘ └───────────┘
─────────────────────────────────────────────────────────
L2: 能力支撑层
┌────────────────────────────┐ ┌────────────────────────────┐
│ Python 微服务 │ │ Dify RAG 平台 │
│ (FastAPI + PyMuPDF) │ │ (知识库 + LLM) │
├────────────────────────────┤ ├────────────────────────────┤
│ - PDF解析 (ASL模块) │ │ - 文档上传分块 │
│ - Docx/Txt提取 (ASL) │ │ - Embedding向量化 │
│ - 数据清洗 (DC模块) │ │ - 向量检索 │
│ - Polars数据处理 │ │ - LLM对话生成 │
│ - OCR识别 (Nougat) │ │ - RAG流程编排 │
│ │ │ │
│ 依赖: │ │ 依赖: │
│ - OSS (读取文件) │ │ - Weaviate (向量存储) │
│ - RDS (存储结果,可选) │ │ - PostgreSQL (Dify专用) │
│ │ │ - Redis (Dify缓存) │
└────────────────────────────┘ └────────────────────────────┘
▲ ▲
│ │
└────────────┬───────────────────┘
│
─────────────────────────────────────────────────────────
L1: 基础设施层
┌────────────────────┐ ┌────────────────┐ ┌──────────────┐
│ PostgreSQL 15 │ │ OSS对象存储 │ │ Redis (可选) │
│ (RDS) │ │ (文件存储) │ │ (Dify专用) │
├────────────────────┤ ├────────────────┤ ├──────────────┤
│ - 10个Schema隔离 │ │ - PDF文件 │ │ - Dify缓存 │
│ - pg-boss任务队列 │ │ - Word/Excel │ │ - Dify会话 │
│ - 用户数据 │ │ - 文献数据 │ │ │
│ - 业务数据 │ │ - 清洗结果 │ │ (初期不需要 │
│ - Prisma ORM访问 │ │ - SDK访问 │ │ Redis,可用 │
│ │ │ - 内网免流量 │ │ Postgres替代)│
└────────────────────┘ └────────────────┘ └──────────────┘
```
### 2. 模块间调用关系表
| 调用方 | 被调用方 | 调用方式 | 调用目的 | 网络 |
|--------|---------|---------|---------|------|
| **前端** | Node.js后端 | HTTP REST API | 所有业务功能 | 公网(HTTPS) |
| **Node.js后端** | Python微服务 | HTTP REST API | PDF解析、数据清洗 | 内网(VPC) |
| **Node.js后端** | Dify API | HTTP REST API | 知识库管理、RAG检索 | 内网(VPC) |
| **Node.js后端** | PostgreSQL | Prisma ORM | 数据CRUD、事务 | 内网(VPC) |
| **Node.js后端** | OSS | SDK (ali-oss) | 文件上传/下载 | 内网(VPC) |
| **Python微服务** | OSS | SDK (oss2) | 读取PDF/Excel | 内网(VPC) |
| **Python微服务** | PostgreSQL | 可选(直接SQL) | 读取配置数据 | 内网(VPC) |
| **Dify** | Weaviate | gRPC | 向量存储/检索 | 本地(Dify内部) |
| **Dify** | PostgreSQL | 原生驱动 | Dify元数据 | 本地(Dify内部) |
| **Dify** | Redis | 原生驱动 | Dify缓存 | 本地(Dify内部) |
**关键原则:**
- ✅ **单一入口**:前端只调用 Node.js后端,不直接调用其他服务
- ✅ **内网通信**:SAE内部服务通过内网互联(免流量费,低延迟)
- ✅ **服务隔离**:Dify独立部署在ECS,通过内网暴露API
- ✅ **数据持久化**:核心数据统一存储在RDS,文件存储在OSS
### 3. 模块责任边界
| 模块 | 核心职责 | 不负责 |
|------|---------|--------|
| **前端** | - 用户交互
- 页面渲染
- 路由管理
- API调用 | ❌ 业务逻辑
❌ 权限校验
❌ 直接访问数据库/OSS |
| **Node.js后端** | - 业务逻辑聚合
- 权限控制
- API网关
- 数据库访问
- 调度微服务 | ❌ PDF解析
❌ 数据清洗
❌ 向量检索 |
| **Python微服务** | - PDF解析
- 文档提取
- 数据清洗
- OCR识别 | ❌ 业务逻辑
❌ 权限控制
❌ 数据库CRUD |
| **Dify平台** | - 知识库管理
- 向量存储
- RAG检索
- LLM对话 | ❌ 用户认证
❌ 业务数据存储
❌ 权限管理 |
| **PostgreSQL** | - 业务数据持久化
- 事务管理
- 任务队列(pg-boss) | ❌ 文件存储
❌ 缓存(可选) |
| **OSS** | - 文件存储
- 静态资源
- 备份归档 | ❌ 结构化数据
❌ 实时计算 |
---
## 模块与阿里云服务映射
### 1. 服务映射表
| 核心模块 | 阿里云服务 | 规格配置 | 成本估算 | 部署文档 |
|---------|-----------|---------|---------|---------|
| **前端 (React)** | SAE容器实例 | 0.5核1GB × 1实例 | ¥50/月 | [06-前端Nginx-SAE容器部署指南](./06-前端Nginx-SAE容器部署指南.md) |
| **Node.js后端** | SAE容器实例 | 1核2GB × 2实例(弹性) | ¥200/月 | [05-Node.js后端-SAE容器部署指南](./05-Node.js后端-SAE容器部署指南.md) |
| **Python微服务** | SAE容器实例 | 1核2GB × 1实例(⚠️ 如OOM升至4GB) | ¥100-200/月 | [04-Python微服务-SAE容器部署指南](./04-Python微服务-SAE容器部署指南.md) |
| **Dify平台** | ECS服务器 | 4核8GB(独立) | ¥300/月 | [03-Dify-ECS部署完全指南](./03-Dify-ECS部署完全指南.md) |
| **PostgreSQL 15** | RDS PostgreSQL | 2核4GB (rds.pg.s2.large) | ¥400/月 | [PostgreSQL部署策略-摸底报告](./PostgreSQL部署策略-摸底报告.md) |
| **文件存储** | OSS标准存储 | 按量付费(50GB) | ¥10/月 | (各模块文档中包含) |
| **⭐ NAT网关** | NAT网关 + EIP | 小规格NAT + 按量EIP | ¥60-100/月 | ⚠️ **必需**(SAE访问公网) |
| **容器镜像** | ACR容器镜像仓库 | 个人版(免费) | ¥0/月 | (各模块文档中包含) |
| **VPC网络** | VPC专有网络 | 默认配置 | ¥0/月 | (各模块文档中包含) |
| **域名/CDN** | (可选)未来配置 | - | ¥50/月 | - |
**总成本估算:** ¥1,200-1,350/月(初期配置,含NAT网关)
⚠️ **成本优化说明:**
- NAT网关(¥100/月)是生产环境标配,不建议省略
- 替代方案:SAE绑定EIP(¥30-50/月,部分地域支持,稳定性较差)或ECS做SNAT(¥0,配置复杂,不推荐)
- Python服务如遇OOM,需升级至4GB内存(增加¥100/月)
### 2. SAE与5个模块的关系
#### 2.1 SAE部署的模块(3个)
```
┌────────────────────────────────────────────────────────────────┐
│ SAE (Serverless Application Engine) │
│ 弹性伸缩 + 按需付费 │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐│
│ │ 前端Nginx容器 │ │ Node.js后端容器 │ │ Python容器 ││
│ ├──────────────────┤ ├──────────────────┤ ├──────────────┤│
│ │ 实例数:1 │ │ 实例数:2-10 │ │ 实例数:1-3 ││
│ │ CPU: 0.5核 │ │ CPU: 1核 │ │ CPU: 1核 ││
│ │ 内存: 1GB │ │ 内存: 2GB │ │ 内存: 2GB ││
│ │ 健康检查: / │ │ 健康检查: /health│ │ 健康检查: /health││
│ │ 自动伸缩: 关闭 │ │ 自动伸缩: 开启 │ │ 自动伸缩: 开启││
│ └──────────────────┘ └──────────────────┘ └──────────────┘│
│ │
│ 共同特性: │
│ ✅ Docker容器部署(镜像从ACR拉取) │
│ ✅ 内网互联(免流量费) │
│ ✅ 自动扩缩容(基于CPU/内存/QPS) │
│ ✅ 滚动发布(零停机部署) │
│ ✅ 健康检查(自动重启异常实例) │
│ ✅ 日志自动收集(stdout/stderr → SLS) │
│ ✅ 环境变量注入(DATABASE_URL等敏感信息) │
│ │
└────────────────────────────────────────────────────────────────┘
```
**SAE的核心价值:**
1. **弹性伸缩**:流量高峰自动扩容,低谷自动缩容
2. **按需付费**:只为实际使用的资源付费
3. **零运维**:无需管理服务器,自动故障转移
4. **快速部署**:从镜像启动实例<30秒
#### 2.2 非SAE部署的模块(2个)
| 模块 | 部署方式 | 原因 |
|------|---------|------|
| **Dify平台** | ECS + Docker Compose | - 服务复杂(7个容器)
- 需要稳定IP(内网调用)
- 独立数据库/Redis
- 不需要弹性伸缩 |
| **PostgreSQL 15** | RDS托管服务 | - 企业级数据库
- 自动备份/PITR
- 高可用(主从)
- 无需自己运维 |
### 3. OSS与5个模块的关系
#### 3.1 OSS使用场景
| 模块 | 使用OSS的场景 | 读/写 | Bucket目录结构 |
|------|--------------|-------|---------------|
| **Node.js后端** | - 用户上传文件
- 文档管理
- 临时文件中转 | 读/写 | `/uploads/{userId}/{fileId}.pdf` |
| **Python微服务** | - 读取PDF进行解析
- 读取Excel进行清洗
- 写入处理结果 | 读/写 | `/asl/literatures/`
`/dc/extracted/` |
| **Dify平台** | - (可选)上传文档到OSS
- Dify内部使用本地存储 | 不使用 | - |
| **前端** | - 不直接访问OSS
- 通过后端API上传/下载 | 不使用 | - |
| **PostgreSQL** | - (可选)备份归档到OSS | 不使用 | `/backups/` |
#### 3.2 OSS Bucket设计
```
aiclinical-data-prod (Bucket名称)
│
├── uploads/ # 用户上传的原始文件
│ ├── {userId}/
│ │ ├── {fileId}.pdf
│ │ ├── {fileId}.docx
│ │ └── {fileId}.xlsx
│ │
├── asl/ # ASL智能文献模块
│ ├── literatures/ # 文献PDF
│ │ └── {projectId}/{litId}.pdf
│ ├── extracted/ # 提取的文本
│ │ └── {projectId}/{litId}.json
│ │
├── dc/ # DC数据清洗模块
│ ├── raw/ # 原始数据文件
│ │ └── {taskId}/data.xlsx
│ ├── cleaned/ # 清洗后的数据
│ │ └── {taskId}/result.xlsx
│ │
├── pkb/ # PKB个人知识库模块
│ ├── documents/ # 知识库文档
│ │ └── {kbId}/{docId}.pdf
│ │
└── backups/ # 数据库备份(可选)
└── {date}/ai_clinical_research.sql.gz
```
**OSS配置要点:**
- ✅ **内网访问**:SAE通过内网访问OSS(免流量费)
- ✅ **权限控制**:使用RAM角色授权,不暴露AccessKey
- ✅ **生命周期**:临时文件30天后自动删除
- ✅ **跨域配置**:如果前端直传,需配置CORS
### 4. RDS与5个模块的关系
#### 4.1 RDS访问权限
| 模块 | 数据库名称 | 访问用户 | 权限 | 连接方式 |
|------|-----------|---------|------|---------|
| **Node.js后端** | ai_clinical_research | aiclinical_rw | SELECT/INSERT/UPDATE/DELETE | Prisma ORM |
| **Python微服务** | ai_clinical_research | aiclinical_rw(可选) | SELECT(只读配置) | psycopg2(可选) |
| **Dify平台** | ❌ 不使用主RDS | - | - | Dify使用独立PostgreSQL |
| **前端** | ❌ 不直接访问 | - | - | 通过后端API |
| **PostgreSQL** | - | postgres(超级用户) | ALL | 仅用于迁移/备份 |
**连接池配置:**
```
总连接数:400(RDS默认)
├── Node.js后端:200 (2实例 × 10连接/实例,预留180)
├── Python微服务:50 (1实例 × 5连接/实例,预留45)
├── pg-boss:50 (后台任务)
├── 预留:100 (管理、备份、临时扩容)
```
---
## 开发环境与部署环境
### 1. 环境对比表
| 维度 | 本地开发环境 | 阿里云部署环境 |
|------|-------------|---------------|
| **前端** | Vite Dev Server (localhost:3000) | SAE Nginx容器 (HTTPS) |
| **Node.js后端** | tsx watch (localhost:3001) | SAE容器 (内网 + 公网) |
| **Python微服务** | uvicorn (localhost:8000) | SAE容器 (内网) |
| **Dify平台** | Docker Compose (localhost) | ECS Docker Compose (内网) |
| **PostgreSQL** | Docker (localhost:5432) | RDS (内网地址) |
| **OSS** | 本地文件系统 (./uploads) | 阿里云OSS |
| **Redis** | ❌ 不使用(Postgres-Only) | ❌ 不使用(Dify独立Redis) |
### 2. 开发与部署的平滑迁移
#### 2.1 配置管理策略
```
项目根目录/
│
├── backend/
│ ├── .env.local # 本地开发配置(不提交Git)
│ ├── .env.example # 配置模板(提交Git)
│ └── src/config/env.ts # 配置加载逻辑
│
├── frontend-v2/
│ ├── .env.local # 本地开发配置
│ ├── .env.production # 生产环境配置模板
│ └── vite.config.ts # Vite配置
│
└── extraction_service/
├── .env.local # 本地开发配置
└── app/config.py # Python配置加载
```
**配置加载优先级:**
```
环境变量 > .env.local > .env > 代码默认值
```
#### 2.2 环境变量对比
**本地开发 (`.env.local`):**
```bash
# 数据库
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ai_clinical_research
# 存储
STORAGE_TYPE=local
LOCAL_STORAGE_DIR=./uploads
# 缓存/队列
CACHE_TYPE=memory
QUEUE_TYPE=memory
# 微服务
DIFY_API_URL=http://localhost/v1
EXTRACTION_SERVICE_URL=http://localhost:8000
```
**阿里云部署(SAE环境变量配置):**
```bash
# 数据库(⚠️ 敏感信息,SAE加密存储)
DATABASE_URL=postgresql://aiclinical_rw:强密码@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical_research?connection_limit=10&pool_timeout=10
# 存储(OSS)
STORAGE_TYPE=oss
OSS_REGION=cn-hangzhou
OSS_BUCKET=aiclinical-data-prod
OSS_ACCESS_KEY_ID=LTAI5***(SAE环境变量)
OSS_ACCESS_KEY_SECRET=***(SAE加密)
# 缓存/队列(Postgres-Only)
CACHE_TYPE=postgres
QUEUE_TYPE=pgboss
# 微服务(内网地址)⚠️ 使用内网IP,不要用.sae域名
DIFY_API_URL=http://172.16.x.x/v1
EXTRACTION_SERVICE_URL=http://172.16.x.x:8000
# ⚠️ 注意:
# - 172.16.x.x 需要替换为实际的内网IP
# - 获取方式:SAE控制台 > 应用详情 > 实例列表 > 查看内网IP
# - ❌ 不要使用 .sae 或 .cluster.local 域名(K8s服务发现需要额外配置)
# 生产环境标识
NODE_ENV=production
```
### 3. 持续部署流程(CI/CD)
#### 3.1 整体流程图
```
┌──────────────────────────────────────────────────────────────────┐
│ 开发者本地开发 │
│ 1. 修改代码 │
│ 2. 本地测试(npm run dev / pytest) │
│ 3. Git提交(git commit -m "feat: xxx") │
│ 4. 推送到远程仓库(git push origin main) │
└────────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ CI/CD 流水线(未来:GitHub Actions) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Stage 1: 构建与测试 │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ - npm install / pip install │ │
│ │ - npm run build / docker build │ │
│ │ - npm test / pytest │ │
│ │ - Lint检查 (eslint / flake8) │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Stage 2: Docker镜像构建 │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ - docker build -t frontend:v1.2.3 │ │
│ │ - docker build -t backend:v1.2.3 │ │
│ │ - docker build -t python-service:v1.2.3 │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Stage 3: 推送到ACR容器镜像仓库 │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ - docker tag ... registry.cn-hangzhou.aliyuncs.com/... │ │
│ │ - docker push registry.cn-hangzhou.aliyuncs.com/... │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Stage 4: 部署到SAE │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ - SAE触发滚动部署 │ │
│ │ - 健康检查 -> 切换流量 │ │
│ │ - 自动回滚(如果失败) │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ 生产环境运行 │
│ - 健康检查监控 │
│ - 日志收集分析 │
│ - 性能指标监控 │
└──────────────────────────────────────────────────────────────────┘
```
#### 3.2 初期手工部署流程(推荐)
**阶段1:初期(1-2人团队,前3个月)**
```bash
# ===== 前端部署 =====
cd frontend-v2
npm run build # 构建生产版本
docker build -t frontend:v1.0.0 . # 构建Docker镜像
docker tag frontend:v1.0.0 registry.cn-hangzhou.aliyuncs.com/your-namespace/frontend:v1.0.0
docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/frontend:v1.0.0
# 在SAE控制台点击"部署" -> 选择新镜像 -> 确认
# ===== 后端部署 =====
cd backend
npm run build # 编译TypeScript
docker build -t backend:v1.0.0 .
docker tag backend:v1.0.0 registry.cn-hangzhou.aliyuncs.com/your-namespace/backend:v1.0.0
docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/backend:v1.0.0
# 在SAE控制台点击"部署" -> 选择新镜像 -> 确认
# ===== Python微服务部署 =====
cd extraction_service
docker build -t python-service:v1.0.0 .
docker tag python-service:v1.0.0 registry.cn-hangzhou.aliyuncs.com/your-namespace/python-service:v1.0.0
docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/python-service:v1.0.0
# 在SAE控制台点击"部署" -> 选择新镜像 -> 确认
```
**优势:**
- ✅ 简单直接,学习成本低
- ✅ 完全可控,出错容易排查
- ✅ 无需配置CI/CD工具
**阶段2:成长期(3-10人团队,3个月后)**
配置GitHub Actions或阿里云云效自动化部署。
#### 3.3 部署频率建议
| 模块 | 部署频率 | 建议时间 | 回滚策略 |
|------|---------|---------|---------|
| **前端** | 每周1-2次 | 周五下午 | SAE一键回滚(保留3个版本) |
| **Node.js后端** | 每周1-2次 | 周五下午 | SAE一键回滚 + 数据库回滚脚本 |
| **Python微服务** | 每2周1次 | 周五下午 | SAE一键回滚 |
| **Dify平台** | 按需(很少) | 周末 | Docker Compose重启旧镜像 |
| **PostgreSQL** | 按需(迁移) | 周末凌晨 | RDS快照恢复 |
### 4. 开发到部署的检查清单
#### 4.1 代码准备
```
☐ 1. 本地测试通过
├─ npm run dev / uvicorn正常运行
├─ 核心功能手工测试
└─ 单元测试/集成测试通过(如果有)
☐ 2. 代码审查
├─ Lint检查通过(eslint / flake8)
├─ 代码格式化(prettier / black)
└─ 无敏感信息泄漏(.env文件不提交)
☐ 3. 环境变量确认
├─ 所有生产环境变量已配置到SAE
├─ 数据库连接字符串正确(含connection_limit)
└─ OSS/Dify等外部服务地址正确
```
#### 4.2 Docker镜像构建
```
☐ 4. Dockerfile优化
├─ 使用多阶段构建(减小镜像体积)
├─ 基础镜像版本固定(如 node:22-alpine,不用latest)
├─ 非root用户运行(安全)
└─ 健康检查配置正确
☐ 5. 镜像构建与测试
├─ docker build成功
├─ docker run本地测试通过
├─ 镜像大小合理(前端<100MB,后端<300MB,Python<1GB)
└─ 镜像打标签(版本号)
```
#### 4.3 部署到SAE
```
☐ 6. 部署前准备
├─ 备份数据库(RDS手动快照)
├─ 通知团队(如果是重大变更)
└─ 准备回滚方案
☐ 7. SAE部署
├─ 推送镜像到ACR
├─ SAE选择新镜像版本
├─ 滚动发布(灰度发布,逐个实例替换)
└─ 观察日志和监控
☐ 8. 部署后验证
├─ 健康检查端点返回200
├─ 核心功能冒烟测试
├─ 日志无ERROR
└─ 监控指标正常(CPU/内存/响应时间)
☐ 9. 回滚准备(如果失败)
├─ SAE一键回滚到上一版本
├─ 数据库恢复快照(如果有Schema变更)
└─ 排查问题日志
```
---
## Docker版本管理策略
### 1. 镜像版本命名规范
#### 1.1 语义化版本 (Semantic Versioning)
```
格式:{服务名}:{主版本}.{次版本}.{修订版本}[-{环境}]
示例:
frontend:1.0.0 # 生产版本
frontend:1.0.0-dev # 开发版本
frontend:1.1.0 # 功能更新
frontend:1.1.1 # Bug修复
```
**版本号规则:**
- **主版本 (Major)**:重大架构变更,不兼容旧版本(如 1.x.x → 2.x.x)
- **次版本 (Minor)**:新增功能,向下兼容(如 1.0.x → 1.1.x)
- **修订版本 (Patch)**:Bug修复,完全兼容(如 1.0.0 → 1.0.1)
#### 1.2 标签策略
| 标签类型 | 示例 | 用途 | 保留策略 |
|---------|------|------|---------|
| **版本号** | `v1.2.3` | 正式发布版本 | 永久保留 |
| **latest** | `latest` | 最新稳定版 | 自动更新 |
| **dev** | `dev` | 开发测试版 | 滚动保留最近10个 |
| **Git SHA** | `sha-a1b2c3d` | 特定提交版本 | 按需保留 |
| **日期** | `20251214` | 按日期归档 | 保留30天 |
**完整示例:**
```bash
# 构建时打多个标签
docker build -t frontend:v1.2.3 \
-t frontend:latest \
-t frontend:sha-a1b2c3d \
-t frontend:20251214 \
.
# 推送到ACR
docker tag frontend:v1.2.3 registry.cn-hangzhou.aliyuncs.com/aiclinical/frontend:v1.2.3
docker tag frontend:v1.2.3 registry.cn-hangzhou.aliyuncs.com/aiclinical/frontend:latest
docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/frontend:v1.2.3
docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/frontend:latest
```
### 2. 本地版本管理
#### 2.1 本地是否需要版本管理?
**答案:初期不需要,成长期建议轻量管理。**
| 阶段 | 本地管理策略 | 原因 |
|------|-------------|------|
| **初期(1-2人)** | ❌ 不需要 | - 开发者少,口头协调即可
- 本地镜像只用于测试
- 直接推送到ACR统一管理 |
| **成长期(3-10人)** | ✅ 轻量管理 | - 使用Git标签管理版本
- `package.json`/`pyproject.toml`记录版本
- 本地镜像定期清理 |
#### 2.2 本地镜像清理
```bash
# 查看本地镜像
docker images | grep frontend
# 删除未使用的镜像(保留最近3个版本)
docker image prune -a --filter "until=720h" # 删除30天前的镜像
# 删除所有未使用的镜像(危险,慎用)
docker image prune -a
```
**建议清理频率:**
- 开发机:每周清理一次
- CI/CD服务器:每次构建后自动清理
### 3. ACR容器镜像仓库管理
#### 3.1 镜像仓库结构
```
阿里云容器镜像服务 (ACR)
├── 命名空间: aiclinical(团队共享)
│ │
│ ├── 仓库: frontend
│ │ ├── latest(自动更新)
│ │ ├── v1.0.0
│ │ ├── v1.0.1
│ │ ├── v1.1.0
│ │ └── ... (保留最近20个版本)
│ │
│ ├── 仓库: backend
│ │ ├── latest
│ │ ├── v1.0.0
│ │ ├── v1.0.1
│ │ └── ...
│ │
│ ├── 仓库: python-service
│ │ ├── latest
│ │ ├── v1.0.0
│ │ └── ...
│ │
│ └── 仓库: dify (可选,如果自定义构建)
│ └── v0.6.13
│
└── 个人版免费配额:3个命名空间,无限仓库数,300GB存储/月
```
#### 3.2 镜像生命周期管理
**保留策略:**
```yaml
规则1: 保留最新的20个版本标签
规则2: 保留所有带"v"前缀的正式版本(v1.0.0、v1.1.0等)
规则3: 自动清理30天前的dev/test标签
规则4: latest标签永久保留
```
**ACR配置示例(控制台配置):**
```
容器镜像服务 > 仓库管理 > frontend > 生命周期规则
├─ 规则1: 保留最近20个版本
│ ├─ 类型: 按数量保留
│ ├─ 保留数量: 20
│ └─ 标签匹配: *
│
└─ 规则2: 清理旧的dev标签
├─ 类型: 按时间清理
├─ 保留时间: 30天
└─ 标签匹配: *-dev
```
### 4. 版本与Git的关系
#### 4.1 Git标签与Docker标签同步
```bash
# 开发流程
git add .
git commit -m "feat: add user profile page"
git push origin main
# 发布版本时创建Git标签
git tag -a v1.2.3 -m "Release v1.2.3: Add user profile"
git push origin v1.2.3
# 构建Docker镜像(版本号与Git标签一致)
docker build -t frontend:v1.2.3 .
docker tag frontend:v1.2.3 registry.cn-hangzhou.aliyuncs.com/aiclinical/frontend:v1.2.3
docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/frontend:v1.2.3
```
#### 4.2 自动版本号管理(可选)
**方法1:从 `package.json` 读取版本号**
```json
// frontend-v2/package.json
{
"name": "aiclinical-frontend",
"version": "1.2.3",
...
}
```
```bash
# 构建脚本自动读取版本号
VERSION=$(node -p "require('./package.json').version")
docker build -t frontend:v$VERSION .
```
**方法2:从Git提交SHA生成版本号**
```bash
# 使用Git SHA作为版本号(适合CI/CD)
GIT_SHA=$(git rev-parse --short HEAD)
docker build -t frontend:sha-$GIT_SHA .
```
### 5. 版本管理工具推荐
| 工具 | 用途 | 适用阶段 |
|------|------|---------|
| **Git Tags** | 代码版本管理 | ✅ 所有阶段 |
| **package.json/pyproject.toml** | 应用版本声明 | ✅ 所有阶段 |
| **Docker Labels** | 镜像元数据标记 | ✅ 成长期+ |
| **语义化版本工具 (semantic-release)** | 自动版本号生成 | 可选(成熟期) |
| **Harbor/ACR版本管理** | 镜像仓库治理 | ✅ 成长期+ |
---
## 线上故障快速修复
### 1. 故障分级与修复策略
| 故障等级 | 影响范围 | 修复策略 | 预期RTO | 示例 |
|---------|---------|---------|---------|------|
| **P0(致命)** | 全站不可用 | 立即回滚 | <5分钟 | 数据库连接失败、应用启动失败 |
| **P1(严重)** | 核心功能不可用 | 回滚或热修复 | <30分钟 | 用户无法登录、文件上传失败 |
| **P2(一般)** | 部分功能异常 | 热修复或下个版本 | <2小时 | 某个页面报错、样式错乱 |
| **P3(轻微)** | 用户体验问题 | 下个版本修复 | <1天 | 文案错误、图标缺失 |
### 2. 修复方案对比
| 修复方法 | 适用场景 | 操作步骤 | 优点 | 缺点 | 推荐度 |
|---------|---------|---------|------|------|--------|
| **方案1:SAE一键回滚** | P0/P1故障 | SAE控制台点击"回滚" | ✅ 最快(<5分钟)
✅ 零风险 | ❌ 回到旧版本,新功能丢失 | ⭐⭐⭐⭐⭐ |
| **方案2:热修复(重新部署完整镜像)** | P1/P2故障 | 修改代码→构建镜像→推送→部署 | ✅ 彻底修复
✅ 保留新功能 | ❌ 慢(10-30分钟)
❌ 需要完整构建 | ⭐⭐⭐⭐ |
| **方案3:单文件热更新(不推荐)** | ❌ 不推荐 | SSH进容器→修改文件 | ✅ 快 | ❌ 容器重启后丢失
❌ 无版本记录
❌ 违反Docker理念 | ⭐ |
| **方案4:配置热更新** | 配置错误 | SAE环境变量→重启应用 | ✅ 快(<5分钟)
✅ 无需重新构建 | ❌ 只适用于配置问题 | ⭐⭐⭐⭐ |
### 3. 详细修复流程
#### 3.1 方案1:SAE一键回滚(推荐)⭐⭐⭐⭐⭐
**适用场景:**
- 新版本部署后发现严重Bug
- 性能急剧下降
- 功能完全不可用
**操作步骤:**
```
步骤1: 登录阿里云控制台 → SAE
步骤2: 选择问题应用(如 aiclinical-backend)
步骤3: 点击"部署历史"
步骤4: 找到上一个稳定版本(如 v1.2.2)
步骤5: 点击"回滚"按钮
步骤6: 确认 → SAE自动执行滚动回滚
步骤7: 观察健康检查和日志
步骤8: 验证功能恢复
预计时间:3-5分钟
```
**SAE回滚机制:**
```
回滚过程(滚动回滚,零停机)
├── 阶段1: 从ACR拉取旧版本镜像
├── 阶段2: 启动1个旧版本实例
├── 阶段3: 健康检查通过后,切换流量到旧实例
├── 阶段4: 逐步停止新版本实例
├── 阶段5: 全部实例回滚完成
└── 时间:2-3分钟(2实例的情况)
```
**回滚后的处理:**
```
☐ 1. 验证核心功能恢复
☐ 2. 通知团队回滚完成
☐ 3. 分析故障原因(日志/监控)
☐ 4. 修复Bug(本地测试充分)
☐ 5. 重新部署修复版本
```
#### 3.2 方案2:热修复(重新部署完整Docker镜像)⭐⭐⭐⭐
**适用场景:**
- 无法回滚(旧版本也有问题)
- Bug已定位且修复简单
- 需要保留新功能
**操作步骤:**
```bash
# ===== 场景:后端API返回500错误 =====
# 步骤1: 本地复现问题
npm run dev
# 测试API: POST /api/v1/users
# 错误日志: TypeError: Cannot read property 'email' of undefined
# 步骤2: 修复代码
# backend/src/modules/users/userService.ts
# 修复:添加空值校验
if (!userData || !userData.email) {
throw new Error('Email is required')
}
# 步骤3: 本地测试通过
npm run dev
# 重新测试API → 200 OK
# 步骤4: 构建新镜像(版本号升级)
npm run build
docker build -t backend:v1.2.4 . # 修订版本号+1
# 步骤5: 推送到ACR
docker tag backend:v1.2.4 registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:v1.2.4
docker push registry.cn-hangzhou.aliyuncs.com/aiclinical/backend:v1.2.4
# 步骤6: SAE部署
# 控制台 → 部署 → 镜像版本: v1.2.4 → 确认 → 滚动发布
# 步骤7: 观察部署过程
# SAE日志实时查看 → 无ERROR → 健康检查通过
# 步骤8: 验证修复
curl -X POST https://api.your-domain.com/api/v1/users \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com"}'
# 返回: 200 OK
# 步骤9: 更新Git
git add .
git commit -m "hotfix: add email validation in userService"
git tag v1.2.4
git push origin main
git push origin v1.2.4
```
**预计时间:10-30分钟**
```
代码修复: 5分钟
构建镜像: 3-5分钟(Node.js后端)
推送镜像: 1-2分钟
SAE部署: 2-3分钟
验证: 2分钟
Git提交: 1分钟
```
#### 3.3 方案3:单文件热更新(❌不推荐,仅紧急情况)
**为什么不推荐?**
1. ❌ **容器重启后丢失**:容器是无状态的,重启后修改消失
2. ❌ **无版本记录**:无法追溯修改历史
3. ❌ **多实例不一致**:SAE有多个实例,只修改一个实例无效
4. ❌ **违反Docker理念**:容器应该是不可变的
**如果必须使用(极端紧急情况):**
```bash
# ⚠️ 仅供紧急情况参考,不推荐
# 步骤1: 登录SAE实例(通过云助手)
# SAE控制台 → 实例列表 → 登录实例
# 步骤2: 找到文件位置
cd /app
ls -la
# 步骤3: 修改文件
vi src/modules/users/userService.js
# 修改错误的代码
# 步骤4: 重启应用(SAE会自动重启)
# ⚠️ 注意:这个修改只在当前实例生效,重启后丢失
# 步骤5: 立即准备正式修复(方案2)
# 本地修改 → 构建镜像 → 部署
```
**总结:除非系统完全崩溃且无法回滚,否则不要使用单文件热更新!**
#### 3.4 方案4:配置热更新(环境变量)⭐⭐⭐⭐
**适用场景:**
- 数据库连接字符串错误
- API密钥/Token过期
- 外部服务地址变更
- Feature Flag开关
**操作步骤:**
```
# 场景:Dify API地址配置错误
步骤1: SAE控制台 → 选择应用 → 环境变量
步骤2: 找到错误的变量
DIFY_API_URL=http://172.16.1.100/v1 # ❌ 错误IP
步骤3: 修改为正确值
DIFY_API_URL=http://172.16.2.50/v1 # ✅ 正确IP
步骤4: 保存 → SAE提示"需要重启应用"
步骤5: 点击"重启应用" → 滚动重启(零停机)
步骤6: 观察日志 → 连接成功
步骤7: 验证功能恢复
预计时间:3-5分钟
```
**环境变量修改的注意事项:**
- ✅ 修改后必须重启应用才能生效
- ✅ 滚动重启,不影响服务可用性
- ⚠️ 敏感信息(密码)修改后,记得更新本地 `.env.example`
- ⚠️ 如果涉及数据库迁移,确保数据库已准备好
### 4. 故障预防与监控
#### 4.1 预防措施
```
☐ 1. 充分的本地测试
├─ 核心功能手工测试
├─ 边界条件测试
└─ 与生产环境类似的数据测试
☐ 2. 灰度发布(SAE支持)
├─ 先部署到1个实例(10%流量)
├─ 观察10-30分钟
└─ 无问题后全量发布
☐ 3. 健康检查完善
├─ /health 端点检查数据库连接
├─ /health 端点检查外部服务(Dify/OSS)
└─ 健康检查失败自动重启
☐ 4. 监控告警
├─ 错误日志告警(SLS)
├─ API响应时间告警(ARMS)
└─ 数据库连接数告警(RDS监控)
☐ 5. 自动化测试(未来)
├─ 单元测试(Jest / Pytest)
├─ 集成测试(Supertest / Playwright)
└─ CI/CD中自动执行
```
#### 4.2 监控指标
| 指标类型 | 监控指标 | 告警阈值 | 处理措施 |
|---------|---------|---------|---------|
| **应用监控** | 错误率 | >5% | 立即查看日志,考虑回滚 |
| **应用监控** | API响应时间 | >2秒 | 检查数据库慢查询、外部服务 |
| **应用监控** | 健康检查失败 | >3次 | 自动重启实例,检查依赖服务 |
| **数据库监控** | 连接数 | >80% | 检查连接泄漏,增加连接池 |
| **数据库监控** | 慢查询 | >1秒 | 优化SQL,添加索引 |
| **容器监控** | CPU使用率 | >70% | 检查死循环,考虑扩容 |
| **容器监控** | 内存使用率 | >80% | 检查内存泄漏,重启实例 |
### 5. 故障修复决策树
```
┌─────────────────┐
│ 发现线上故障 │
└────────┬────────┘
│
┌────────▼────────┐
│ 影响范围评估? │
└────┬────────────┘
│
┌──────────┼──────────┐
│ │
┌───────▼────────┐ ┌──────▼────────┐
│ 全站不可用 │ │ 部分功能异常 │
│ (P0/P1) │ │ (P2/P3) │
└───────┬────────┘ └──────┬────────┘
│ │
┌───────▼────────┐ ┌──────▼────────┐
│ 能否快速定位? │ │ 能否快速修复? │
└───┬────────┬───┘ └──┬────────┬───┘
│ No │ Yes │ Yes │ No
│ │ │ │
┌─────▼──┐ ┌──▼─────┐ ┌──▼──┐ ┌───▼────┐
│ 立即 │ │ 是配置 │ │ 热修│ │ 下个版 │
│ 回滚 │ │ 问题? │ │ 复 │ │ 本修复 │
└────────┘ └──┬──┬──┘ └─────┘ └────────┘
│ │
┌─────▼──▼────┐
│ 修改环境变量 │
│ + 重启应用 │
└──────────────┘
```
---
## 部署文档导航
### 📚 独立部署文档清单
| # | 文档名称 | 部署对象 | 目标环境 | 预计时间 |
|---|---------|---------|---------|---------|
| 1 | [PostgreSQL部署策略-摸底报告](./PostgreSQL部署策略-摸底报告.md) | PostgreSQL 15数据库 | RDS PostgreSQL 15 | 10分钟(pg_dump导入) |
| 2 | [Dify-ECS部署完全指南](./03-Dify-ECS部署完全指南.md) | Dify RAG平台 | ECS + Docker Compose | 30-60分钟 |
| 3 | [Python微服务-SAE容器部署指南](./04-Python微服务-SAE容器部署指南.md) | Python微服务 | SAE容器实例 | 20-30分钟 |
| 4 | [Node.js后端-SAE容器部署指南](./05-Node.js后端-SAE容器部署指南.md) | Node.js后端 | SAE容器实例 | 20-30分钟 |
| 5 | [前端Nginx-SAE容器部署指南](./06-前端Nginx-SAE容器部署指南.md) | React前端 | SAE容器实例 | 15-20分钟 |
**总部署时间:** 约2-3小时(从0到全部上线)
### 🎯 部署顺序建议
```
第一阶段:基础设施(Day 1)⭐ 必需
├── 1. 创建VPC和安全组 (10分钟)
├── 2. ⭐ 创建NAT网关 + 绑定EIP (15分钟) ← 新增,必需!
├── 3. 部署RDS PostgreSQL 15 (10分钟,等待实例创建15分钟)
├── 4. 导入数据库(pg_dump) (5分钟)
└── 5. 创建OSS Bucket (5分钟)
└── 配置生命周期、权限
第二阶段:核心服务(Day 1)⚠️ 临时配置
├── 6. 部署Node.js后端到SAE (20分钟)
│ └── ⚠️ DIFY_API_KEY=temp(临时值,等Dify部署后更新)
├── 7. 部署Python微服务到SAE (20分钟)
└── 8. 端到端测试(后端API + Python服务) (15分钟)
第三阶段:用户界面(Day 2)
├── 9. 部署前端到SAE (15分钟)
└── 10. 完整功能测试(不含PKB模块) (30分钟)
第四阶段:Dify服务(Day 2-3)⭐ PKB模块必需
├── 11. 部署Dify到ECS (60分钟)
├── 12. 登录Dify生成API Key (5分钟)
├── 13. 更新后端DIFY_API_KEY环境变量 (5分钟)
└── 14. 测试PKB知识库功能 (15分钟)
总计:约4-5小时(实际操作时间,不含等待)
```
### 📖 如何使用这些文档?
#### 新团队首次部署
```
步骤1: 阅读本《部署架构总览》
├─ 理解整体架构
├─ 理解模块依赖关系
└─ 熟悉阿里云服务
步骤2: 按顺序阅读独立部署文档
├─ PostgreSQL部署策略(理解数据库架构)
├─ Node.js后端部署(核心服务)
├─ Python微服务部署(能力支撑)
├─ 前端Nginx部署(用户界面)
└─ Dify部署(可选,PKB模块需要)
步骤3: 准备阿里云账号和资源
├─ 实名认证
├─ 充值(建议¥500起步)
├─ 创建RAM子账号(安全)
└─ 开通SAE/RDS/OSS/ACR服务
步骤4: 按第一阶段→第二阶段→第三阶段顺序部署
└─ 每个阶段完成后测试验证
步骤5: 监控与优化
├─ 配置告警规则
├─ 观察7天运行情况
└─ 根据实际情况调整规格
```
#### 已有系统维护
```
日常开发部署:
├─ 修改代码
├─ 本地测试
├─ 构建Docker镜像
├─ 推送到ACR
└─ SAE控制台部署
线上故障处理:
├─ 参考"线上故障快速修复"章节
├─ P0/P1: 立即回滚
├─ P2/P3: 热修复或下个版本
└─ 故障复盘,更新文档
新模块上线:
├─ 参考对应的独立部署文档
├─ 确认依赖服务(数据库/OSS/其他服务)
├─ 灰度发布(先1个实例)
└─ 全量发布
```
### 🔗 文档间的引用关系
```
00-部署架构总览.md (本文档)
│
├──► PostgreSQL部署策略-摸底报告.md
│ ├─ 数据库架构详解
│ ├─ pg_dump导入流程
│ ├─ 备份策略
│ └─ 最佳实践
│
├──► 03-Dify-ECS部署完全指南.md
│ ├─ Docker Compose配置
│ ├─ Nginx路由层
│ ├─ Swap配置
│ └─ 故障排查
│
├──► 04-Python微服务-SAE容器部署指南.md
│ ├─ Dockerfile多阶段构建
│ ├─ 系统依赖安装(PyTorch/OpenCV)
│ ├─ SAE配置
│ └─ 内网调用
│
├──► 05-Node.js后端-SAE容器部署指南.md
│ ├─ Prisma反向同步(db pull)
│ ├─ 数据库连接池
│ ├─ 优雅关闭
│ └─ 环境变量配置
│
└──► 06-前端Nginx-SAE容器部署指南.md
├─ SPA路由配置
├─ API反向代理
├─ 静态资源缓存
└─ envsubst动态配置
```
---
## 🛡️ 安全与最佳实践
### 1. 时区统一配置 ⭐⭐⭐⭐⭐
**问题:** 不同服务的时区不一致会导致:
- 日志时间对不上(前端14:00,后端06:00)
- pg-boss定时任务在错误时间触发
- 用户看到的时间戳错误
**解决:** 所有服务统一使用 `Asia/Shanghai` 时区
```dockerfile
# backend/Dockerfile - Node.js后端
FROM node:22-alpine AS runtime
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
# ... 其他配置
# extraction_service/Dockerfile - Python微服务
FROM python:3.11-slim AS runtime
RUN apt-get update && apt-get install -y tzdata
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# ... 其他配置
# frontend-v2/Dockerfile - 前端(已配置)
FROM nginx:1.25-alpine
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
# ... 其他配置
```
```sql
-- RDS PostgreSQL 时区配置
-- RDS控制台 > 参数设置 > timezone
timezone = Asia/Shanghai
```
**验证时区:**
```bash
# 查看容器时区
docker exec date
# 应该显示:Sat Dec 14 14:30:00 CST 2024
# 查看RDS时区
psql -c "SHOW timezone;"
# 应该显示:Asia/Shanghai
```
### 2. 安全组配置最佳实践 ⭐⭐⭐⭐⭐
#### ECS安全组配置(Dify服务器)
**正确配置:**
```bash
# ECS控制台 > 安全组 > 配置规则
# ✅ 入方向规则(Inbound)
允许 80/TCP 来源:172.16.0.0/12 # Nginx(VPC内网访问)
允许 22/TCP 来源:您的办公室公网IP # SSH管理
拒绝 所有 来源:0.0.0.0/0 # 默认拒绝
```
**⚠️ 安全红线(绝对禁止):**
```bash
# ❌ 禁止 5000/TCP(Dify API)对公网开放
# 后果:黑客可绕过后端消耗LLM额度
# ❌ 禁止 8080/TCP(Weaviate)对公网开放
# 后果:向量数据可能被窃取
# ❌ 禁止 6379/TCP(Redis)对公网开放
# 后果:Redis无密码,可能被清空
# ✅ 正确:docker-compose.yaml中端口绑定
services:
redis:
ports:
- "127.0.0.1:6379:6379" # 只监听本地
weaviate:
ports:
- "127.0.0.1:8080:8080" # 只监听本地
```
**验证安全配置:**
```bash
# 从公网测试(应该失败)
telnet ECS公网IP 6379
# 应该超时或拒绝连接
# 从VPC内测试(应该成功)
curl http://172.16.x.x # Dify内网地址
# 应该返回 Dify 响应
```
🔗 **详细配置:** 参考 `03-Dify-ECS部署完全指南.md`
### 3. 镜像拉取策略 ⭐⭐⭐⭐⭐
**问题:** SAE可能不会拉取新镜像(代码不更新的"灵异事件")
```bash
# 场景:
开发者修改代码 → 构建镜像 → 推送到ACR(覆盖v1.0.0)
→ SAE部署 → 发现代码没更新???
# 原因:
SAE默认镜像拉取策略可能是 IfNotPresent
如果本地已有 v1.0.0,不会重新拉取
```
**解决方案:**
| 方案 | 适用环境 | 优势 | 劣势 |
|------|---------|------|------|
| **方案A:版本号管理** | 生产环境 | 版本可追溯,稳定 | 需手动递增版本号 |
| **方案B:Always拉取** | 测试环境 | 始终最新,方便 | 每次重启拉取,慢 |
**方案A:每次部署使用新版本号(强烈推荐)**
```bash
# 使用语义化版本号
v1.0.0 → v1.0.1 → v1.0.2 ...
# 或使用时间戳
v20251214-1430 → v20251214-1530 ...
# 或使用Git SHA
v-a1b2c3d → v-b2c3d4e ...
```
**方案B:配置SAE镜像拉取策略**
```bash
# SAE控制台 > 应用配置 > 镜像设置
镜像拉取策略:Always
# ⚠️ 注意:
# - 每次重启都会拉取镜像(启动稍慢)
# - 适合测试环境,不推荐生产环境
```
### 4. 开发调试最佳实践
#### 本地连接RDS数据库(SSH隧道)
**场景:** 开发人员需要用Navicat/DBeaver查看RDS数据
**问题:** RDS在VPC内网,本地无法直接访问
**解决:** 通过ECS建立SSH隧道
```bash
# 步骤1:建立SSH隧道
ssh -N -L 5433:rm-xxxxx.pg.rds.aliyuncs.com:5432 \
root@ECS公网IP \
-i ~/.ssh/dify-ecs.pem
# 参数说明:
# -N: 不执行远程命令,只建立隧道
# -L: 本地端口转发
# 5433: 本地监听端口(避免与本地PostgreSQL 5432冲突)
# rm-xxxxx: RDS内网地址
# 5432: RDS端口
# 步骤2:Navicat/DBeaver连接配置
主机:localhost
端口:5433
用户名:aiclinical_rw
密码:(RDS密码)
数据库:ai_clinical_research
# 步骤3:测试连接
# 应该成功连接到RDS!
```
**后台运行(可选):**
```bash
# 方法1:nohup后台运行
nohup ssh -N -L 5433:rm-xxxxx.pg.rds.aliyuncs.com:5432 \
root@ECS-IP -i key.pem > /dev/null 2>&1 &
# 方法2:保持隧道运行(新终端窗口)
ssh -N -L 5433:rm-xxxxx.pg.rds.aliyuncs.com:5432 \
root@ECS-IP -i key.pem
# 保持此终端窗口打开
```
🔗 **详细步骤参考:** `07-关键配置补充说明.md` 第7节
### 5. Python服务内存管理 ⭐⭐⭐⭐
**问题:** Python服务(PyMuPDF/Nougat)内存密集,容易OOM
| 场景 | CPU | 内存 | Workers | 适用情况 |
|------|-----|------|---------|---------|
| **基础版** | 1核 | 2GB | 2 | 简单PDF解析 |
| **标准版** | 2核 | 4GB | 3 | 包含OCR(Nougat) |
| **增强版** | 2核 | 8GB | 4 | 大量OCR + 高并发 |
**⚠️ 重要提示:**
- 如果遇到OOM(Out of Memory),优先升级内存至4GB
- 或者限制Gunicorn并发数:`--workers 1 --threads 2`
- PyMuPDF + Nougat OCR单个请求可能占用500MB-1GB内存
**Dockerfile优化(已应用):**
```dockerfile
CMD ["gunicorn", "main:app", \
"--bind", "0.0.0.0:8000", \
"--workers", "2", \
"--timeout", "120", \
"--max-requests", "100", \
"--max-requests-jitter", "10"]
```
🔗 **详细配置:** 参考 `04-Python微服务-SAE容器部署指南.md`
### 6. NAT网关成本优化
**当前方案:NAT网关(推荐)**
```
成本:NAT网关¥60/月 + EIP流量费¥30-50/月 = ¥90-110/月
优势:稳定可靠,生产环境标配
劣势:成本相对较高
```
**替代方案(不推荐,仅供参考):**
| 方案 | 成本 | 稳定性 | 复杂度 | 推荐度 |
|------|------|--------|--------|--------|
| NAT网关 | ¥100/月 | ⭐⭐⭐⭐⭐ | 低 | ⭐⭐⭐⭐⭐(推荐)|
| SAE绑定EIP | ¥30-50/月 | ⭐⭐⭐ | 中 | ⭐⭐⭐(部分地域)|
| ECS做SNAT | ¥0(复用ECS) | ⭐⭐ | 高 | ⭐⭐(不推荐)|
**建议:** 初创团队不要在这里省钱,NAT网关是生产环境的标配。
---
## 📝 总结与建议
### 核心架构特点
1. **✅ 云原生Serverless架构**
- 前端/后端/Python全部容器化部署到SAE
- 弹性伸缩,按需付费
- 零运维,自动故障转移
2. **✅ 微服务隔离**
- 5个核心模块职责清晰
- 内网通信,免流量费
- 独立部署,互不影响
3. **✅ 数据安全可控**
- PostgreSQL 10个Schema隔离
- RDS自动备份 + PITR
- VPC内网隔离,白名单控制
4. **✅ 适合初创团队**
- 1-2人可运维
- 手工部署简单直接
- 成本可控(¥1,100/月起)
### 下一步行动
```
☐ 第1周:基础设施搭建
├─ 阿里云账号准备
├─ VPC/RDS/OSS创建
└─ 数据库导入
☐ 第2周:核心服务部署
├─ Node.js后端上线
├─ Python微服务上线
├─ 前端上线
└─ 端到端测试
☐ 第3周:可选服务 + 监控
├─ Dify部署(如需PKB模块)
├─ 配置监控告警
└─ 压力测试
☐ 第4周:稳定性优化
├─ 根据监控数据调整资源
├─ 故障演练(回滚、修复)
└─ 文档完善
```
### 持续改进建议
| 阶段 | 改进方向 | 优先级 |
|------|---------|--------|
| **3个月内** | - 完善监控告警
- 编写运维手册
- 故障演练 | ⭐⭐⭐⭐⭐ |
| **6个月内** | - 配置CI/CD
- 自动化测试
- 性能优化 | ⭐⭐⭐⭐ |
| **1年内** | - 跨地域灾备
- 容器编排升级(ACK)
- 微服务治理 | ⭐⭐⭐ |
---
**文档创建人:** AI助手
**最后更新:** 2025-12-14
**版本:** v1.0
**核心理念:架构清晰、职责分离、云原生、易于运维** ⭐⭐⭐