Features - User Management (Phase 4.1): - Database: Add user_modules table for fine-grained module permissions - Database: Add 4 user permissions (view/create/edit/delete) to role_permissions - Backend: UserService (780 lines) - CRUD with tenant isolation - Backend: UserController + UserRoutes (648 lines) - 13 API endpoints - Backend: Batch import users from Excel - Frontend: UserListPage (412 lines) - list/filter/search/pagination - Frontend: UserFormPage (341 lines) - create/edit with module config - Frontend: UserDetailPage (393 lines) - details/tenant/module management - Frontend: 3 modal components (592 lines) - import/assign/configure - API: GET/POST/PUT/DELETE /api/admin/users/* endpoints Architecture Upgrade - Module Permission System: - Backend: Add getUserModules() method in auth.service - Backend: Login API returns modules array in user object - Frontend: AuthContext adds hasModule() method - Frontend: Navigation filters modules based on user.modules - Frontend: RouteGuard checks requiredModule instead of requiredVersion - Frontend: Remove deprecated version-based permission system - UX: Only show accessible modules in navigation (clean UI) - UX: Smart redirect after login (avoid 403 for regular users) Fixes: - Fix UTF-8 encoding corruption in ~100 docs files - Fix pageSize type conversion in userService (String to Number) - Fix authUser undefined error in TopNavigation - Fix login redirect logic with role-based access check - Update Git commit guidelines v1.2 with UTF-8 safety rules Database Changes: - CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled) - ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code) - INSERT 4 permissions + role assignments - UPDATE PUBLIC tenant with 8 module subscriptions Technical: - Backend: 5 new files (~2400 lines) - Frontend: 10 new files (~2500 lines) - Docs: 1 development record + 2 status updates + 1 guideline update - Total: ~4900 lines of code Status: User management 100% complete, module permission system operational
1606 lines
72 KiB
Markdown
1606 lines
72 KiB
Markdown
# 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. 模块责任边界
|
||
|
||
| 模块 | 核心职责 | 不负责 |
|
||
|------|---------|--------|
|
||
| **前端** | - 用户交互<br>- 页面渲染<br>- 路由管理<br>- API调用 | ❌ 业务逻辑<br>❌ 权限校验<br>❌ 直接访问数据库/OSS |
|
||
| **Node.js后端** | - 业务逻辑聚合<br>- 权限控制<br>- API网关<br>- 数据库访问<br>- 调度微服务 | ❌ PDF解析<br>❌ 数据清洗<br>❌ 向量检索 |
|
||
| **Python微服务** | - PDF解析<br>- 文档提取<br>- 数据清洗<br>- OCR识别 | ❌ 业务逻辑<br>❌ 权限控制<br>❌ 数据库CRUD |
|
||
| **Dify平台** | - 知识库管理<br>- 向量存储<br>- RAG检索<br>- LLM对话 | ❌ 用户认证<br>❌ 业务数据存储<br>❌ 权限管理 |
|
||
| **PostgreSQL** | - 业务数据持久化<br>- 事务管理<br>- 任务队列(pg-boss) | ❌ 文件存储<br>❌ 缓存(可选) |
|
||
| **OSS** | - 文件存储<br>- 静态资源<br>- 备份归档 | ❌ 结构化数据<br>❌ 实时计算 |
|
||
|
||
---
|
||
|
||
## 模块与阿里云服务映射
|
||
|
||
### 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个容器)<br>- 需要稳定IP(内网调用)<br>- 独立数据库/Redis<br>- 不需要弹性伸缩 |
|
||
| **PostgreSQL 15** | RDS托管服务 | - 企业级数据库<br>- 自动备份/PITR<br>- 高可用(主从)<br>- 无需自己运维 |
|
||
|
||
### 3. OSS与5个模块的关系
|
||
|
||
#### 3.1 OSS使用场景
|
||
|
||
| 模块 | 使用OSS的场景 | 读/写 | Bucket目录结构 |
|
||
|------|--------------|-------|---------------|
|
||
| **Node.js后端** | - 用户上传文件<br>- 文档管理<br>- 临时文件中转 | 读/写 | `/uploads/{userId}/{fileId}.pdf` |
|
||
| **Python微服务** | - 读取PDF进行解析<br>- 读取Excel进行清洗<br>- 写入处理结果 | 读/写 | `/asl/literatures/`<br>`/dc/extracted/` |
|
||
| **Dify平台** | - (可选)上传文档到OSS<br>- Dify内部使用本地存储 | 不使用 | - |
|
||
| **前端** | - 不直接访问OSS<br>- 通过后端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人)** | ❌ 不需要 | - 开发者少,口头协调即可<br>- 本地镜像只用于测试<br>- 直接推送到ACR统一管理 |
|
||
| **成长期(3-10人)** | ✅ 轻量管理 | - 使用Git标签管理版本<br>- `package.json`/`pyproject.toml`记录版本<br>- 本地镜像定期清理 |
|
||
|
||
#### 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分钟)<br>✅ 零风险 | ❌ 回到旧版本,新功能丢失 | ⭐⭐⭐⭐⭐ |
|
||
| **方案2:热修复(重新部署完整镜像)** | P1/P2故障 | 修改代码→构建镜像→推送→部署 | ✅ 彻底修复<br>✅ 保留新功能 | ❌ 慢(10-30分钟)<br>❌ 需要完整构建 | ⭐⭐⭐⭐ |
|
||
| **方案3:单文件热更新(不推荐)** | ❌ 不推荐 | SSH进容器→修改文件 | ✅ 快 | ❌ 容器重启后丢失<br>❌ 无版本记录<br>❌ 违反Docker理念 | ⭐ |
|
||
| **方案4:配置热更新** | 配置错误 | SAE环境变量→重启应用 | ✅ 快(<5分钟)<br>✅ 无需重新构建 | ❌ 只适用于配置问题 | ⭐⭐⭐⭐ |
|
||
|
||
### 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 <container-id> 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个月内** | - 完善监控告警<br>- 编写运维手册<br>- 故障演练 | ⭐⭐⭐⭐⭐ |
|
||
| **6个月内** | - 配置CI/CD<br>- 自动化测试<br>- 性能优化 | ⭐⭐⭐⭐ |
|
||
| **1年内** | - 跨地域灾备<br>- 容器编排升级(ACK)<br>- 微服务治理 | ⭐⭐⭐ |
|
||
|
||
---
|
||
|
||
**文档创建人:** AI助手
|
||
**最后更新:** 2025-12-14
|
||
**版本:** v1.0
|
||
|
||
**核心理念:架构清晰、职责分离、云原生、易于运维** ⭐⭐⭐
|
||
|