feat(dc): Add multi-metric transformation feature (direction 1+2)
Summary: - Implement intelligent multi-metric grouping detection algorithm - Add direction 1: timepoint-as-row, metric-as-column (analysis format) - Add direction 2: timepoint-as-column, metric-as-row (display format) - Fix column name pattern detection (FMA___ issue) - Maintain original Record ID order in output - Add full-select/clear buttons in UI - Integrate into TransformDialog with Radio selection - Update 3 documentation files Technical Details: - Python: detect_metric_groups(), apply_multi_metric_to_long(), apply_multi_metric_to_matrix() - Backend: 3 new methods in QuickActionService - Frontend: MultiMetricPanel.tsx (531 lines) - Total: ~1460 lines of new code Status: Fully tested and verified, ready for production
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
# 部署架构设计
|
||||
|
||||
> **文档版本:** v1.0
|
||||
> **创建日期:** 2025-10-29
|
||||
> **维护者:** 架构团队
|
||||
> **最后更新:** 2025-10-29
|
||||
|
||||
---
|
||||
|
||||
## 📋 文档说明
|
||||
|
||||
本文档描述系统的部署架构设计,包括:
|
||||
- 部署模式(云部署、本地化部署、混合部署)
|
||||
- 部署方案(Docker、Kubernetes等)
|
||||
- 环境配置
|
||||
- 模块独立部署方案
|
||||
|
||||
---
|
||||
|
||||
## ⏳ 待完善
|
||||
|
||||
本文档内容待规划完善,目前仅作为占位文档。
|
||||
|
||||
---
|
||||
|
||||
**文档版本:** v1.0
|
||||
**最后更新:** 2025-10-29
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -854,3 +854,9 @@ ACR镜像仓库:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ RAG 系统迁移的复杂度:
|
||||
专有网络 VPC: 选择 SAE 所在的 VPC
|
||||
安全组: 创建新安全组,配置入方向规则(⚠️ 安全红线):
|
||||
✅ 允许 22/TCP 来源:您的办公室公网IP # SSH管理
|
||||
✅ 允许 80/TCP 来源:172.16.0.0/12 # Nginx(VPC内网访问)
|
||||
✅ 允许 80/TCP 来源:172.17.0.0/16 # Nginx(VPC内网访问)
|
||||
❌ 拒绝 5000/TCP 来源:0.0.0.0/0 # Dify API禁止公网访问
|
||||
❌ 拒绝 6379/TCP 来源:0.0.0.0/0 # Redis禁止公网访问
|
||||
❌ 拒绝 8080/TCP 来源:0.0.0.0/0 # Weaviate禁止公网访问
|
||||
@@ -177,7 +177,7 @@ RAG 系统迁移的复杂度:
|
||||
|
||||
⚠️ 安全警告:
|
||||
- Dify API (5000)、Redis (6379)、Weaviate (8080) 绝对不能对公网开放
|
||||
- 只允许VPC内网访问(172.16.0.0/12)
|
||||
- 只允许VPC内网访问(172.17.0.0/16)
|
||||
- 端口绑定到 127.0.0.1(见docker-compose.yaml配置)
|
||||
```
|
||||
|
||||
|
||||
@@ -540,19 +540,19 @@ docker rm extraction-test
|
||||
```bash
|
||||
# 1. 登录阿里云容器镜像服务
|
||||
# 获取登录命令:阿里云控制台 → 容器镜像服务 → 访问凭证 → 设置Registry登录密码
|
||||
docker login --username=<your-username> registry.cn-hangzhou.aliyuncs.com
|
||||
docker login --username=<your-username> registry.cn-beijing.aliyuncs.com
|
||||
|
||||
# 2. 给镜像打标签
|
||||
docker tag extraction-service:latest \
|
||||
registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:v1.0
|
||||
registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:v1.0
|
||||
|
||||
# 3. 推送到阿里云
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:v1.0
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:v1.0
|
||||
|
||||
# 4. 推送 latest 标签(便于后续更新)
|
||||
docker tag extraction-service:latest \
|
||||
registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:latest
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:latest
|
||||
registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:latest
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:latest
|
||||
```
|
||||
|
||||
---
|
||||
@@ -572,7 +572,7 @@ docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-servi
|
||||
|
||||
3. **镜像配置**:
|
||||
```
|
||||
镜像地址: registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:latest
|
||||
镜像地址: registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:latest
|
||||
镜像版本: latest
|
||||
镜像拉取策略: Always(每次部署都拉取最新镜像)
|
||||
```
|
||||
@@ -690,7 +690,7 @@ TZ=Asia/Shanghai
|
||||
3. **查看并复制"内网访问地址"**,通常是以下格式之一:
|
||||
```
|
||||
# 格式 1: 内网 IP + 端口(⭐⭐⭐⭐⭐ 强烈推荐,最稳定)
|
||||
172.16.0.10:8000
|
||||
172.17.x.x:8000
|
||||
|
||||
# 格式 2: SAE 内网 Service 域名(需要额外配置服务发现,不推荐)
|
||||
extraction-service-xxxxx.cn-hangzhou.sae.aliyuncs.com:8000
|
||||
@@ -716,7 +716,7 @@ TZ=Asia/Shanghai
|
||||
5. **✅ 推荐做法(按优先级排序)**:
|
||||
```bash
|
||||
# ⭐⭐⭐⭐⭐ 方案A:直接使用内网IP(强烈推荐)
|
||||
EXTRACTION_SERVICE_URL=http://172.16.0.10:8000
|
||||
EXTRACTION_SERVICE_URL=http://172.17.x.x:8000
|
||||
# 获取方式:SAE控制台 > Python应用 > 实例列表 > 查看内网IP
|
||||
|
||||
# ⭐⭐⭐ 方案B:使用SAE服务发现(需要额外配置,不推荐初期使用)
|
||||
@@ -730,7 +730,7 @@ TZ=Asia/Shanghai
|
||||
|
||||
```bash
|
||||
# ⚠️ 使用 SAE 控制台显示的真实内网地址
|
||||
EXTRACTION_SERVICE_URL=http://172.16.0.10:8000
|
||||
EXTRACTION_SERVICE_URL=http://172.17.x.x:8000
|
||||
|
||||
# 注意:
|
||||
# 1. 不要使用猜测的域名
|
||||
@@ -817,7 +817,7 @@ export async function testExtractionService() {
|
||||
|
||||
2. **查看 Node.js 后端日志**(SAE 控制台 → 后端应用 → 日志):
|
||||
```
|
||||
[INFO] Calling extraction service: http://172.16.0.10:8000/extract/pdf
|
||||
[INFO] Calling extraction service: http://172.17.x.x:8000/extract/pdf
|
||||
[INFO] Extraction completed in 2.3s
|
||||
[INFO] Extracted text preview: "This is a test document..."
|
||||
```
|
||||
@@ -1050,7 +1050,7 @@ pip list --outdated
|
||||
|
||||
# 2. 重建镜像(包含安全更新)
|
||||
docker build -t extraction-service:v1.1 .
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:v1.1
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:v1.1
|
||||
|
||||
# 3. 在 SAE 中更新镜像版本
|
||||
```
|
||||
@@ -1131,7 +1131,7 @@ with open(pdf_path, 'rb') as f:
|
||||
```
|
||||
后端日志:Connection refused
|
||||
或
|
||||
ECONNREFUSED: connect ECONNREFUSED 172.16.0.10:8000
|
||||
ECONNREFUSED: connect ECONNREFUSED 172.17.x.x:8000
|
||||
或
|
||||
Error: getaddrinfo ENOTFOUND extraction-service.internal
|
||||
```
|
||||
@@ -1144,7 +1144,7 @@ Error: getaddrinfo ENOTFOUND extraction-service.internal
|
||||
EXTRACTION_SERVICE_URL=http://extraction-service.internal:8000
|
||||
|
||||
# ✅ 正确配置(SAE 控制台显示的真实地址)
|
||||
EXTRACTION_SERVICE_URL=http://172.16.0.10:8000
|
||||
EXTRACTION_SERVICE_URL=http://172.17.x.x:8000
|
||||
```
|
||||
|
||||
**解决方法**:
|
||||
@@ -1300,7 +1300,7 @@ EXTRACTION_SERVICE_URL=http://extraction-service:8000
|
||||
# ✅ 正确做法:从 SAE 控制台获取真实地址
|
||||
# SAE 控制台 → extraction-service 应用 → 应用访问配置
|
||||
# 复制显示的"VPC 内网访问地址"
|
||||
EXTRACTION_SERVICE_URL=http://172.16.0.10:8000
|
||||
EXTRACTION_SERVICE_URL=http://172.17.x.x:8000
|
||||
```
|
||||
|
||||
**原因**:
|
||||
@@ -1498,7 +1498,7 @@ echo "Done!"
|
||||
docker build -t extraction-service:v1.0 .
|
||||
|
||||
# 推送镜像
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/extraction-service:v1.0
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/extraction-service:v1.0
|
||||
|
||||
# 查看 SAE 日志
|
||||
# SAE 控制台 → 应用详情 → 日志
|
||||
|
||||
@@ -93,7 +93,7 @@ npm --version
|
||||
- [ ] **RDS PostgreSQL 15** 实例已创建并运行
|
||||
- 数据库名称:`ai_clinical`(或自定义)
|
||||
- 用户名和密码已准备
|
||||
- 内网地址已获取(如 `rm-xxxxx.pg.rds.aliyuncs.com:5432`)
|
||||
- 内网地址已获取(如 `pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432`)
|
||||
- 白名单已配置(允许 SAE VPC 访问)
|
||||
|
||||
- [ ] **阿里云容器镜像服务 ACR** 已开通
|
||||
@@ -104,8 +104,8 @@ npm --version
|
||||
- VPC 和交换机已选择(与 RDS 在同一 VPC)
|
||||
|
||||
- [ ] **依赖服务的内网地址已获取**:
|
||||
- Python 微服务(SAE):`http://172.16.0.10:8000`
|
||||
- Dify 服务(ECS):`http://172.16.0.20:80`
|
||||
- Python 微服务(SAE):`http://172.17.x.x:8000`
|
||||
- Dify 服务(ECS):`http://172.17.x.x:80`
|
||||
|
||||
#### 敏感信息准备
|
||||
|
||||
@@ -113,7 +113,7 @@ npm --version
|
||||
|
||||
```bash
|
||||
# 数据库
|
||||
DATABASE_URL=postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical?connection_limit=18&pool_timeout=10
|
||||
DATABASE_URL=postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical?connection_limit=18&pool_timeout=10
|
||||
|
||||
# LLM API Keys(至少配置一个)
|
||||
DEEPSEEK_API_KEY=sk-xxxxx
|
||||
@@ -122,10 +122,10 @@ CLOSEAI_API_KEY=sk-xxxxx
|
||||
|
||||
# Dify
|
||||
DIFY_API_KEY=app-xxxxx
|
||||
DIFY_API_URL=http://172.16.0.20:80/v1
|
||||
DIFY_API_URL=http://172.17.x.x:80/v1
|
||||
|
||||
# 阿里云 OSS
|
||||
OSS_REGION=oss-cn-hangzhou
|
||||
OSS_REGION=oss-cn-beijing
|
||||
OSS_BUCKET=clinical-research-files
|
||||
OSS_ACCESS_KEY_ID=LTAI5t...
|
||||
OSS_ACCESS_KEY_SECRET=xxx...
|
||||
@@ -157,10 +157,10 @@ Node.js 后端(SAE)
|
||||
├──→ RDS PostgreSQL 15(数据库)
|
||||
│
|
||||
├──→ Python 微服务(SAE) - 文档提取
|
||||
│ └─ http://172.16.0.10:8000
|
||||
│ └─ http://172.17.x.x:8000
|
||||
│
|
||||
├──→ Dify 服务(ECS) - RAG 知识库
|
||||
│ └─ http://172.16.0.20:80/v1
|
||||
│ └─ http://172.17.x.x:80/v1
|
||||
│
|
||||
└──→ 阿里云 OSS - 文件存储
|
||||
└─ clinical-research-files
|
||||
@@ -247,7 +247,7 @@ cp backend/.env backend/.env.backup
|
||||
|
||||
# 2. 创建临时 RDS 连接配置
|
||||
cat > backend/.env.rds <<EOF
|
||||
DATABASE_URL="postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical?connection_limit=18&pool_timeout=10"
|
||||
DATABASE_URL="postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical?connection_limit=18&pool_timeout=10"
|
||||
EOF
|
||||
|
||||
# 3. 使用 RDS 配置
|
||||
@@ -263,7 +263,7 @@ npx prisma db pull
|
||||
|
||||
# 输出示例:
|
||||
# Prisma schema loaded from prisma/schema.prisma
|
||||
# Datasource "db": PostgreSQL database "ai_clinical" at "rm-xxxxx.pg.rds.aliyuncs.com:5432"
|
||||
# Datasource "db": PostgreSQL database "ai_clinical" at "pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432"
|
||||
#
|
||||
# Introspecting based on datasource defined in prisma/schema.prisma …
|
||||
#
|
||||
@@ -348,7 +348,7 @@ git push
|
||||
|
||||
```bash
|
||||
# 错误信息:
|
||||
Error: P1001: Can't reach database server at `rm-xxxxx.pg.rds.aliyuncs.com:5432`
|
||||
Error: P1001: Can't reach database server at `pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432`
|
||||
```
|
||||
|
||||
**解决方法**:
|
||||
@@ -359,7 +359,7 @@ Error: P1001: Can't reach database server at `rm-xxxxx.pg.rds.aliyuncs.com:5432`
|
||||
# 添加你的本地公网 IP(查询:curl ipinfo.io)
|
||||
|
||||
# 2. 测试连接
|
||||
psql "postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
psql "postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
|
||||
# 如果能连上,再执行 npx prisma db pull
|
||||
```
|
||||
@@ -885,7 +885,7 @@ SERVICE_NAME=backend-service
|
||||
|
||||
```bash
|
||||
# ⚠️ 使用 RDS 内网地址
|
||||
DATABASE_URL=postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical?connection_limit=18&pool_timeout=10
|
||||
DATABASE_URL=postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical?connection_limit=18&pool_timeout=10
|
||||
|
||||
# 连接池配置(根据 RDS 规格调整)
|
||||
DB_MAX_CONNECTIONS=400
|
||||
@@ -903,7 +903,7 @@ MAX_INSTANCES=20
|
||||
```bash
|
||||
# 使用阿里云 OSS
|
||||
STORAGE_TYPE=oss
|
||||
OSS_REGION=oss-cn-hangzhou
|
||||
OSS_REGION=oss-cn-beijing
|
||||
OSS_BUCKET=clinical-research-files
|
||||
OSS_ACCESS_KEY_ID=LTAI5t...
|
||||
OSS_ACCESS_KEY_SECRET=xxx...
|
||||
@@ -939,7 +939,7 @@ CLOSEAI_CLAUDE_BASE_URL=https://api.openai-proxy.org/anthropic
|
||||
|
||||
```bash
|
||||
# ⚠️ 使用 ECS 内网 IP(不要使用公网域名)
|
||||
DIFY_API_URL=http://172.16.0.20:80/v1
|
||||
DIFY_API_URL=http://172.17.x.x:80/v1
|
||||
DIFY_API_KEY=app-xxxxx
|
||||
```
|
||||
|
||||
@@ -1079,7 +1079,7 @@ ls -lh ai_clinical_backup_*.sql
|
||||
|
||||
```bash
|
||||
# 连接到 RDS 并导入
|
||||
psql "postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical" \
|
||||
psql "postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical" \
|
||||
< ai_clinical_backup_20251213.sql
|
||||
|
||||
# 输出示例:
|
||||
@@ -1101,7 +1101,7 @@ psql "postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinic
|
||||
|
||||
```bash
|
||||
# 连接到 RDS
|
||||
psql "postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
psql "postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
|
||||
# 查看所有 Schema
|
||||
\dn
|
||||
@@ -1160,7 +1160,7 @@ ls -l prisma/schema.prisma
|
||||
|
||||
```bash
|
||||
# 1. 连接到 RDS
|
||||
export DATABASE_URL="postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
export DATABASE_URL="postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
|
||||
# 2. 执行迁移
|
||||
cd backend
|
||||
@@ -1319,7 +1319,7 @@ curl -X POST https://backend-service-xxxxx.cn-hangzhou.sae.aliyuncs.com/api/asl/
|
||||
|
||||
# 查看后端日志(SAE 控制台 → 应用详情 → 日志)
|
||||
# 应该看到:
|
||||
# [INFO] Calling extraction service: http://172.16.0.10:8000/extract/pdf
|
||||
# [INFO] Calling extraction service: http://172.17.x.x:8000/extract/pdf
|
||||
# [INFO] Extraction completed in 3.2s
|
||||
```
|
||||
|
||||
@@ -1337,7 +1337,7 @@ curl -X POST https://backend-service-xxxxx.cn-hangzhou.sae.aliyuncs.com/api/know
|
||||
|
||||
# 查看后端日志
|
||||
# 应该看到:
|
||||
# [INFO] Calling Dify API: http://172.16.0.20:80/v1/chat-messages
|
||||
# [INFO] Calling Dify API: http://172.17.x.x:80/v1/chat-messages
|
||||
# [INFO] Dify response received in 2.5s
|
||||
```
|
||||
|
||||
@@ -1512,14 +1512,14 @@ SAE 控制台显示:实例启动中 → 健康检查失败 → 实例停止
|
||||
# 解决:检查 SAE 环境变量配置,补充缺失的变量
|
||||
|
||||
# 错误 B:数据库连接失败
|
||||
# 日志:❌ 数据库连接失败: getaddrinfo ENOTFOUND rm-xxxxx.pg.rds.aliyuncs.com
|
||||
# 日志:❌ 数据库连接失败: getaddrinfo ENOTFOUND pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com
|
||||
# 解决:
|
||||
# - 检查 DATABASE_URL 是否正确
|
||||
# - 检查 RDS 白名单是否允许 SAE VPC 访问
|
||||
# - 检查 RDS 内网地址是否可达
|
||||
|
||||
# 错误 C:Prisma 迁移未执行
|
||||
# 日志:Error: P1001: Can't reach database server at `rm-xxxxx.pg.rds.aliyuncs.com`
|
||||
# 日志:Error: P1001: Can't reach database server at `pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com`
|
||||
# 解决:先执行数据库迁移(参见第 8 节)
|
||||
|
||||
# 错误 D:端口冲突
|
||||
@@ -1607,7 +1607,7 @@ DATABASE_URL=postgresql://...?connection_limit=10&pool_timeout=10
|
||||
```
|
||||
[ERROR] Failed to connect to Python service: ECONNREFUSED
|
||||
或
|
||||
[ERROR] connect ETIMEDOUT 172.16.0.10:8000
|
||||
[ERROR] connect ETIMEDOUT 172.17.x.x:8000
|
||||
```
|
||||
|
||||
**排查步骤**:
|
||||
@@ -1622,7 +1622,7 @@ DATABASE_URL=postgresql://...?connection_limit=10&pool_timeout=10
|
||||
|
||||
# 3. 测试内网连通性
|
||||
# 在后端应用的 Webshell 中执行:
|
||||
curl -v http://172.16.0.10:8000/health
|
||||
curl -v http://172.17.x.x:8000/health
|
||||
|
||||
# 4. 检查安全组规则
|
||||
# SAE 控制台 → extraction-service 应用 → 网络配置
|
||||
@@ -1666,7 +1666,7 @@ curl http://localhost/v1/info
|
||||
|
||||
# 3. 从 SAE 测试连通性
|
||||
# 在后端应用的 Webshell 中执行:
|
||||
curl -v http://172.16.0.20:80/v1/info
|
||||
curl -v http://172.17.x.x:80/v1/info
|
||||
```
|
||||
|
||||
**解决方法**:
|
||||
@@ -1700,7 +1700,7 @@ DIFY_API_URL=http://<ECS内网IP>:80/v1
|
||||
# 1. 检查环境变量
|
||||
# SAE 控制台 → 应用详情 → 环境变量
|
||||
# 确认以下变量正确:
|
||||
OSS_REGION=oss-cn-hangzhou
|
||||
OSS_REGION=oss-cn-beijing
|
||||
OSS_BUCKET=clinical-research-files
|
||||
OSS_ACCESS_KEY_ID=LTAI5t...
|
||||
OSS_ACCESS_KEY_SECRET=xxx...
|
||||
@@ -1825,7 +1825,7 @@ PrismaClientKnownRequestError: column "phone" does not exist
|
||||
|
||||
```bash
|
||||
# 1. 在本地开发环境,连接到 RDS
|
||||
export DATABASE_URL="postgresql://username:password@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
export DATABASE_URL="postgresql://username:password@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical"
|
||||
|
||||
# 2. 反向同步 Schema
|
||||
npx prisma db pull
|
||||
@@ -2006,7 +2006,7 @@ pg_dump → 导入 RDS → prisma db pull(同步)→ 构建镜像 → 部署
|
||||
|
||||
```typescript
|
||||
// ❌ 错误示例
|
||||
const dbUrl = 'postgresql://admin:P@ssw0rd@rm-xxxxx.pg.rds.aliyuncs.com:5432/ai_clinical';
|
||||
const dbUrl = 'postgresql://admin:P@ssw0rd@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical';
|
||||
|
||||
// ✅ 正确做法
|
||||
const dbUrl = process.env.DATABASE_URL;
|
||||
|
||||
@@ -106,7 +106,7 @@ npm run build
|
||||
#### 阿里云资源
|
||||
|
||||
- [ ] **后端服务(SAE)** 已部署并运行
|
||||
- 后端 VPC 内网地址已获取(如 `http://172.16.0.30:3001`)
|
||||
- 后端 VPC 内网地址已获取(如 `http://172.17.x.x:3001`)
|
||||
- 后端健康检查可访问
|
||||
|
||||
- [ ] **阿里云容器镜像服务 ACR** 已开通
|
||||
@@ -120,7 +120,7 @@ npm run build
|
||||
|
||||
```bash
|
||||
# 后端服务内网地址(关键)
|
||||
BACKEND_SERVICE_URL=http://172.16.0.30:3001
|
||||
BACKEND_SERVICE_URL=http://172.17.x.x:3001
|
||||
|
||||
# 如果需要配置环境变量(可选)
|
||||
# VITE_API_BASE_URL 在构建时注入(很少使用)
|
||||
@@ -217,7 +217,7 @@ ASL 模块:GET /api/v1/asl/projects
|
||||
↓
|
||||
Nginx 反向代理
|
||||
↓
|
||||
后端服务:http://172.16.0.30:3001/api/v1/asl/projects
|
||||
后端服务:http://172.17.x.x:3001/api/v1/asl/projects
|
||||
```
|
||||
|
||||
### 📝 构建流程
|
||||
@@ -363,7 +363,7 @@ http {
|
||||
server ${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT} fail_timeout=30s max_fails=3;
|
||||
|
||||
# 如果有多个后端实例(负载均衡)
|
||||
# server 172.16.0.30:3001 weight=1;
|
||||
# server 172.17.x.x:3001 weight=1;
|
||||
# server 172.16.0.31:3001 weight=1;
|
||||
|
||||
keepalive 32; # 保持连接池
|
||||
@@ -485,7 +485,7 @@ http {
|
||||
access_log off;
|
||||
# 仅允许内网访问
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 172.17.0.0/16;
|
||||
allow 192.168.0.0/16;
|
||||
deny all;
|
||||
}
|
||||
@@ -547,7 +547,7 @@ Nginx:接收请求
|
||||
↓
|
||||
Nginx:proxy_pass http://backend
|
||||
↓
|
||||
后端服务:http://172.16.0.30:3001/api/v1/projects
|
||||
后端服务:http://172.17.x.x:3001/api/v1/projects
|
||||
↓
|
||||
后端返回数据
|
||||
↓
|
||||
@@ -806,7 +806,7 @@ nginx.conf.template(模板):
|
||||
↓ envsubst 替换
|
||||
|
||||
nginx.conf(最终配置):
|
||||
server 172.16.0.30:3001;
|
||||
server 172.17.x.x:3001;
|
||||
```
|
||||
|
||||
#### 3. 健康检查
|
||||
@@ -987,7 +987,7 @@ docker rm frontend-test
|
||||
|
||||
```bash
|
||||
# 登录(使用 ACR 密码,不是阿里云账号密码)
|
||||
docker login --username=your-aliyun-account registry.cn-hangzhou.aliyuncs.com
|
||||
docker login --username=your-aliyun-account registry.cn-beijing.aliyuncs.com
|
||||
|
||||
# 输入密码后看到:
|
||||
# Login Succeeded
|
||||
@@ -998,21 +998,21 @@ docker login --username=your-aliyun-account registry.cn-hangzhou.aliyuncs.com
|
||||
```bash
|
||||
# 格式:registry地址/命名空间/仓库名:版本号
|
||||
docker tag frontend-service:v1.0.0 \
|
||||
registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service:v1.0.0
|
||||
registry.cn-beijing.aliyuncs.com/clinical-research/frontend-service:v1.0.0
|
||||
|
||||
# 同时打一个 latest 标签
|
||||
docker tag frontend-service:v1.0.0 \
|
||||
registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service:latest
|
||||
registry.cn-beijing.aliyuncs.com/clinical-research/frontend-service:latest
|
||||
```
|
||||
|
||||
### 步骤 3:推送镜像
|
||||
|
||||
```bash
|
||||
# 推送指定版本
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service:v1.0.0
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/frontend-service:v1.0.0
|
||||
|
||||
# 推送 latest
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service:latest
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/frontend-service:latest
|
||||
|
||||
# 推送过程需要 1-3 分钟(镜像很小)
|
||||
```
|
||||
@@ -1055,7 +1055,7 @@ docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service
|
||||
| 配置项 | 值 |
|
||||
|-------|-----|
|
||||
| **镜像类型** | 容器镜像服务企业版实例 |
|
||||
| **镜像仓库** | `registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service` |
|
||||
| **镜像仓库** | `registry.cn-beijing.aliyuncs.com/clinical-research/frontend-service` |
|
||||
| **镜像版本** | `v1.0.0` |
|
||||
| **镜像拉取策略** | 总是拉取镜像 |
|
||||
|
||||
@@ -1085,7 +1085,7 @@ docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service
|
||||
|
||||
```bash
|
||||
# ⚠️ 必须配置(否则容器启动失败)
|
||||
BACKEND_SERVICE_HOST=172.16.0.30
|
||||
BACKEND_SERVICE_HOST=172.17.x.x
|
||||
|
||||
# 可选配置(默认 3001)
|
||||
BACKEND_SERVICE_PORT=3001
|
||||
@@ -1108,7 +1108,7 @@ upstream backend {
|
||||
server ${BACKEND_SERVICE_URL}; # ❌ 无法解析 http://172.16.0.30:3001
|
||||
|
||||
# 拆分后:
|
||||
server 172.16.0.30:3001; # ✅ 正确
|
||||
server 172.17.x.x:3001; # ✅ 正确
|
||||
```
|
||||
|
||||
### 步骤 5:配置健康检查
|
||||
@@ -1337,7 +1337,7 @@ API 代理:响应时间 50-500ms(取决于后端)
|
||||
# ✅ 正常启动
|
||||
============================================
|
||||
Starting Frontend Nginx Service
|
||||
Backend Service: 172.16.0.30:3001
|
||||
Backend Service: 172.17.x.x:3001
|
||||
============================================
|
||||
nginx: configuration file /etc/nginx/nginx.conf test is successful
|
||||
|
||||
@@ -1354,7 +1354,7 @@ nginx: configuration file /etc/nginx/nginx.conf test is successful
|
||||
# ❌ 错误日志(后端连接失败)
|
||||
2025/12/13 10:30:04 [error] 7#7: *1 connect() failed (111: Connection refused) while connecting to upstream
|
||||
client: 172.31.0.10, server: _, request: "GET /api/v1/projects HTTP/1.1"
|
||||
upstream: "http://172.16.0.30:3001/api/v1/projects"
|
||||
upstream: "http://172.17.x.x:3001/api/v1/projects"
|
||||
```
|
||||
|
||||
#### 3. Nginx 状态监控
|
||||
@@ -1419,7 +1419,7 @@ curl http://localhost/nginx_status
|
||||
cd frontend
|
||||
npm run build
|
||||
docker build -t frontend-service:v1.0.1 .
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/clinical-research/frontend-service:v1.0.1
|
||||
docker push registry.cn-beijing.aliyuncs.com/clinical-research/frontend-service:v1.0.1
|
||||
|
||||
# 2. 在 SAE 中更新镜像
|
||||
# SAE 控制台 → 应用详情 → 部署
|
||||
@@ -1556,7 +1556,7 @@ location / {
|
||||
|
||||
# 2. 测试后端内网地址是否可达
|
||||
# 登录前端应用的 Webshell:
|
||||
curl http://172.16.0.30:3001/api/v1/health
|
||||
curl http://172.17.x.x:3001/api/v1/health
|
||||
|
||||
# 如果返回错误,说明:
|
||||
# - 后端服务未启动
|
||||
@@ -1567,7 +1567,7 @@ curl http://172.16.0.30:3001/api/v1/health
|
||||
cat /etc/nginx/nginx.conf | grep -A 5 "upstream backend"
|
||||
|
||||
# 应该看到正确的后端地址:
|
||||
# server 172.16.0.30:3001 fail_timeout=30s max_fails=3;
|
||||
# server 172.17.x.x:3001 fail_timeout=30s max_fails=3;
|
||||
|
||||
# 4. 查看 Nginx 错误日志
|
||||
tail -f /var/log/nginx/error.log | grep "upstream"
|
||||
@@ -1579,14 +1579,14 @@ tail -f /var/log/nginx/error.log | grep "upstream"
|
||||
# 方法 1:更新环境变量
|
||||
# SAE 控制台 → frontend-service → 应用配置 → 环境变量
|
||||
# 确认:
|
||||
BACKEND_SERVICE_HOST=172.16.0.30 # 正确的内网 IP
|
||||
BACKEND_SERVICE_HOST=172.17.x.x # 正确的内网 IP
|
||||
BACKEND_SERVICE_PORT=3001
|
||||
|
||||
# 重启应用使环境变量生效
|
||||
|
||||
# 方法 2:测试内网连通性
|
||||
# 在前端 Webshell 中:
|
||||
telnet 172.16.0.30 3001
|
||||
telnet 172.17.x.x 3001
|
||||
# 如果连接失败,检查:
|
||||
# - 后端和前端是否在同一 VPC
|
||||
# - 安全组规则是否允许访问
|
||||
@@ -1744,7 +1744,7 @@ cat /docker-entrypoint.sh | grep "envsubst"
|
||||
cat /etc/nginx/nginx.conf | grep "server.*backend"
|
||||
|
||||
# 应该看到:
|
||||
# server 172.16.0.30:3001;
|
||||
# server 172.17.x.x:3001;
|
||||
|
||||
# 如果看到:
|
||||
# server ${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT}; # ❌ 未替换
|
||||
@@ -1809,11 +1809,11 @@ export default defineConfig({
|
||||
|
||||
```bash
|
||||
# ✅ 正确做法:拆分 Host 和 Port
|
||||
BACKEND_SERVICE_HOST=172.16.0.30
|
||||
BACKEND_SERVICE_HOST=172.17.x.x
|
||||
BACKEND_SERVICE_PORT=3001
|
||||
|
||||
# ❌ 错误做法:完整 URL
|
||||
BACKEND_SERVICE_URL=http://172.16.0.30:3001
|
||||
BACKEND_SERVICE_URL=http://172.17.x.x:3001
|
||||
# Nginx 无法解析协议前缀
|
||||
```
|
||||
|
||||
|
||||
@@ -465,3 +465,9 @@ NAT网关成本¥100/月,对初创团队是一笔开销
|
||||
**审查依据:** 专业技术团队反馈
|
||||
**修正质量:** ⭐⭐⭐⭐⭐(8/8问题已全部修正)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user