Files
AIclinicalresearch/docs/05-部署文档/_archive-2025首次部署/17-完整部署实战手册-2025版.md
HaHafeng 6124c7abc6 docs(platform): Add database documentation system and restructure deployment docs
Completed:
- Add 6 core database documents (docs/01-平台基础层/07-数据库/)
  Architecture overview, migration history, environment comparison,
  tech debt tracking, seed data management, PostgreSQL extensions
- Restructure deployment docs: archive 20 legacy files to _archive-2025/
- Create unified daily operations manual (01-日常更新操作手册.md)
- Add pending deployment change tracker (03-待部署变更清单.md)
- Update database development standard to v3.0 (three iron rules)
- Fix Prisma schema type drift: align @db.* annotations with actual DB
  IIT: UUID/Timestamptz(6), SSA: Timestamp(6)/VarChar(20/50/100)
- Add migration: 20260227_align_schema_with_db_types (idempotent ALTER)
- Add Cursor Rule for auto-reminding deployment change documentation
- Update system status guide v6.4 with deployment and DB doc references
- Add architecture consultation docs (Prisma guide, SAE deployment guide)

Technical details:
- Manual migration due to shadow DB limitation (TD-001 in tech debt)
- Deployment docs reduced from 20+ scattered files to 3 core documents
- Cursor Rule triggers on schema.prisma, package.json, Dockerfile changes

Made-with: Cursor
2026-02-27 14:35:25 +08:00

1845 lines
40 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI临床研究平台 - 完整部署实战手册2025版
> **文档版本**v1.0(实战版)
> **创建日期**2025-12-25
> **基于实际部署**2025-12-24 ~ 2025-12-25 完整部署经历
> **部署成功时间**约6小时包含问题排查
> **部署人员**:开发团队
> **部署结果**:✅ 完全成功,所有功能正常运行
---
## 📋 文档说明
### 本文档的特点
-**基于真实部署经历**记录了2025年12月实际部署的完整过程
-**包含所有坑点**遇到的4个关键问题及解决方案
-**经验总结**:提炼出的最佳实践和注意事项
-**可直接复制**:所有配置和命令都经过验证
-**适合快速部署**:跟着做就能成功
### 与其他文档的关系
| 文档名称 | 用途 | 何时使用 |
|---------|------|---------|
| **本文档** | 实战部署完整流程 | ⭐ 新部署或重新部署时 |
| `01-快速部署SOP-零基础版.md` | 零基础完整指南 | 从零开始学习时 |
| `00-部署进度总览.md` | 资源速查索引 | 查询资源信息时 |
| `12-Node.js后端-SAE部署操作手册.md` | 单服务部署 | 只部署某个服务时 |
---
## 🎯 部署架构总览
```
用户浏览器
↓ HTTPS (公网)
CLB负载均衡器 (公网IP: 8.140.53.236)
↓ HTTP (内网)
前端Nginx (SAE: 172.17.173.72:80)
↓ HTTP (内网, /api/v1/)
Node.js后端 (SAE: 172.17.173.73:3001)
↓ HTTP (内网, /api/dc/)
Python服务 (SAE: 172.17.173.66:8000)
↓ SQL (内网)
RDS PostgreSQL (内网: pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432)
```
**关键依赖**
- 所有服务在同一个VPC内网`172.17.0.0/16`
- 使用NAT网关访问外网拉取镜像、调用LLM API
- CLB绑定前端提供公网访问
---
## 📊 部署顺序(严格按顺序执行)
| 步骤 | 服务 | 预计时间 | 依赖项 |
|------|------|---------|--------|
| 1⃣ | VPC网络 + NAT网关 | 15分钟 | 无 |
| 2⃣ | RDS PostgreSQL | 30分钟 | VPC |
| 3⃣ | OSS对象存储 | 10分钟 | 无 |
| 4⃣ | ACR容器镜像仓库 | 10分钟 | 无 |
| 5⃣ | Python微服务镜像构建 | 20分钟 | ACR |
| 6⃣ | Python微服务部署到SAE | 15分钟 | VPC, ACR |
| 7⃣ | Node.js后端镜像构建 | 30分钟 | ACR, RDS |
| 8⃣ | Node.js后端部署到SAE | 20分钟 | VPC, ACR, RDS, Python |
| 9⃣ | 前端Nginx镜像构建 | 15分钟 | ACR |
| 🔟 | 前端Nginx部署到SAE | 15分钟 | VPC, ACR, Node.js |
| 1⃣1⃣ | CLB负载均衡器 | 10分钟 | 前端Nginx |
| 1⃣2⃣ | 全链路测试验证 | 30分钟 | 所有服务 |
**总计**约3.5小时(不含问题排查)
---
## 🔑 一、前置准备30分钟
### 1.1 阿里云账号与资源
**检查清单**
- [ ] 阿里云账号已实名认证
- [ ] 账户余额 ≥ 500元建议1000元
- [ ] 地域选择华北2北京
- [ ] 已创建RAM访问密钥用于Docker登录
### 1.2 本地开发环境
**必需工具**
- [ ] Docker DesktopWindows/Mac或 Docker EngineLinux
- [ ] Git用于代码管理
- [ ] Node.js 22+(用于本地构建)
- [ ] PowerShell 或 Bash执行脚本
**验证命令**
```bash
docker --version # 应显示 Docker version 24.0+
git --version # 应显示 git version 2.x+
node --version # 应显示 v22.x.x
```
### 1.3 项目代码准备
```bash
# 克隆项目(如果还没有)
git clone <your-repo-url> AIclinicalresearch
cd AIclinicalresearch
# 确认项目结构
ls -la
# 应该看到backend/, frontend-v2/, extraction_service/, docs/
```
---
## 🌐 二、基础设施部署1小时
### 2.1 VPC网络15分钟
**登录VPC控制台**https://vpc.console.aliyun.com/
#### 创建VPC
1. 点击【创建专有网络】
2. 配置参数:
```yaml
VPC名称: ai-clinical-vpc
地域: 华北2北京
IPv4网段: 172.17.0.0/16
```
3. 点击【确定】
#### 创建交换机2个提高可用性
**交换机1**
```yaml
名称: ai-clinical-vsw-f
可用区: 华北2 可用区F
IPv4网段: 172.17.160.0/20
```
**交换机2**
```yaml
名称: ai-clinical-vsw-a
可用区: 华北2 可用区A
IPv4网段: 172.17.192.0/20
```
#### 创建安全组
1. 进入【安全组】页面
2. 创建安全组:
```yaml
名称: ai-clinical-sg
网络: ai-clinical-vpc
```
3. 配置入方向规则:
```yaml
# 允许VPC内网互通
协议: 全部
端口: -1/-1
授权对象: 172.17.0.0/16
# 允许HTTPS (443)
协议: TCP
端口: 443/443
授权对象: 0.0.0.0/0
# 允许HTTP (80)
协议: TCP
端口: 80/80
授权对象: 0.0.0.0/0
```
---
### 2.2 NAT网关15分钟
**用途**让VPC内的SAE应用能访问外网拉取镜像、调用LLM API
#### 创建NAT网关
**登录NAT网关控制台**https://vpc.console.aliyun.com/nat/
1. 点击【创建NAT网关】
2. 配置参数:
```yaml
名称: NAT_airesearch
地域: 华北2北京
VPC: ai-clinical-vpc
交换机: ai-clinical-vsw-f
网关类型: 增强型
付费模式: 按量付费
```
3. 点击【立即购买】
#### 创建并绑定EIP
1. 在NAT网关详情页点击【绑定弹性公网IP】
2. 选择【购买新的EIP】
```yaml
计费方式: 按使用流量
带宽峰值: 5Mbps测试环境够用
```
3. 购买并绑定
#### 配置SNAT条目关键
1. 进入NAT网关详情 → 【SNAT管理】
2. 添加SNAT条目1
```yaml
交换机: ai-clinical-vsw-f
公网IP: 选择刚才的EIP
```
3. 添加SNAT条目2
```yaml
交换机: ai-clinical-vsw-a
公网IP: 选择刚才的EIP
```
**验证**
- SNAT条目状态显示【可用】✅
---
### 2.3 RDS PostgreSQL30分钟
**登录RDS控制台**https://rdsnext.console.aliyun.com/
#### 创建实例
1. 点击【创建实例】
2. 配置参数:
```yaml
# 基础配置
地域: 华北2北京
可用区: 可用区F与交换机对应
数据库引擎: PostgreSQL
版本: 15
系列: 高可用版
存储类型: ESSD云盘
# 规格
规格类型: 通用型
规格: 2核4GB (pg.n2.2c.1m)
存储空间: 100GB
# 网络
网络类型: 专有网络
VPC: ai-clinical-vpc
交换机: ai-clinical-vsw-f
# 付费
付费类型: 按量付费(测试)或 包年包月(生产)
```
3. 点击【立即购买】
#### 创建数据库和账号
**等待实例创建完成约10分钟**,然后:
1. 进入实例详情 → 【账号管理】
2. 创建高权限账号:
```yaml
账号名称: airesearch
账号密码: Xibahe@fengzhibo117 # 改为您的强密码
账号类型: 高权限账号
```
3. 进入【数据库管理】
4. 创建数据库:
```yaml
数据库名称: ai_clinical_research
字符集: UTF8
排序规则: en_US.utf8
授权账号: airesearch (读写)
```
#### 配置白名单
1. 进入【数据安全性】→ 【白名单设置】
2. 修改默认分组:
```yaml
白名单: 172.17.0.0/16 # VPC网段
```
#### 配置时区(重要!)
1. 进入【参数设置】
2. 搜索 `timezone`
3. 修改为:`Asia/Shanghai`
4. 点击【提交参数】
#### 导入数据
**方法1使用本地数据库导出**(推荐)
```bash
# 从本地Docker导出
docker exec ai-clinical-postgres pg_dump \
-U postgres \
-d ai_clinical_research \
--format=plain \
--no-owner \
--no-acl \
--encoding=UTF8 \
> rds_init.sql
# 临时开启RDS外网地址仅用于导入
# 在RDS控制台 → 数据库连接 → 申请外网地址
# 导入到RDS需要容器内有psql客户端
cat rds_init.sql | docker exec -i -e PGPASSWORD="Xibahe@fengzhibo117" \
ai-clinical-postgres psql \
-h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \
-p 5432 -U airesearch -d ai_clinical_research
# 导入完成后,立即关闭外网地址(安全)
```
**验证**
```bash
# 连接到RDS检查
docker exec -e PGPASSWORD="Xibahe@fengzhibo117" \
ai-clinical-postgres psql \
-h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \
-p 5432 -U airesearch -d ai_clinical_research \
-c "SELECT nspname FROM pg_namespace WHERE nspname LIKE '%_schema' ORDER BY nspname;"
# 应该看到asl_schema, dc_schema, platform_schema 等
```
---
### 2.4 OSS对象存储10分钟
**登录OSS控制台**https://oss.console.aliyun.com/
#### 创建Bucket
1. 点击【创建Bucket】
2. 配置参数:
```yaml
Bucket名称: ai-clinical-research
地域: 华北2北京
存储类型: 标准存储
读写权限: 私有
存储冗余类型: 同城冗余存储
版本控制: 关闭
```
3. 点击【确定】
#### 创建RAM访问密钥
1. 进入【访问控制RAM】https://ram.console.aliyun.com/
2. 创建用户:
```yaml
登录名称: oss-bucket-writer
显示名称: OSS Bucket写入用户
访问方式: ✅ OpenAPI调用访问
```
3. 保存AccessKey
```yaml
AccessKeyId: LTAI5tB2Dt3NdvBL3G7nYGv7
AccessKeySecret: 1iSN9k39RkApP93QjUhC1DcPIeMG4V
```
**⚠️ 立即复制保存,后续无法查看!**
4. 为用户授权:
- 选择用户 → 【添加权限】
- 选择权限:`AliyunOSSFullAccess`(或自定义权限)
---
### 2.5 ACR容器镜像仓库10分钟
**登录容器镜像服务**https://cr.console.aliyun.com/
#### 创建命名空间
1. 进入【个人实例】→ 【命名空间】
2. 点击【创建命名空间】:
```yaml
命名空间名称: ai-clinical
```
#### 创建镜像仓库3个
**仓库1Python微服务**
```yaml
命名空间: ai-clinical
仓库名称: python-extraction
仓库类型: 私有
摘要: Python文档提取服务
```
**仓库2Node.js后端**
```yaml
命名空间: ai-clinical
仓库名称: backend-service
仓库类型: 私有
摘要: Node.js后端API服务
```
**仓库3前端Nginx**
```yaml
命名空间: ai-clinical
仓库名称: ai-clinical_frontend-nginx
仓库类型: 私有
摘要: React前端Nginx服务
```
#### 设置访问凭证
**在本地Docker登录ACR**
```bash
# 个人版ACR登录公网地址
docker login \
--username=gofeng117@163.com \
--password=fengzhibo117 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
# 登录成功提示
# Login Succeeded
```
**记录镜像地址格式**
```bash
# 公网地址(本地推送用)
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/<仓库名>:<标签>
# VPC地址SAE拉取用
crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/<仓库名>:<标签>
```
---
## 🐍 三、Python微服务部署35分钟
### 3.1 构建Docker镜像20分钟
#### 进入目录
```bash
cd AIclinicalresearch/extraction_service
```
#### 检查Dockerfile
确认Dockerfile存在且内容正确
```dockerfile
# 应该包含:
FROM python:3-slim
# ... 安装依赖
COPY requirements-prod.txt .
RUN pip install --no-cache-dir -r requirements-prod.txt
# ... 复制代码
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```
#### 构建镜像
```bash
# 构建镜像
docker build -t python-extraction:v1.0 .
# 等待构建完成约10-15分钟
# Successfully built...
# Successfully tagged python-extraction:v1.0
```
#### 本地测试(可选但推荐)
```bash
# 运行容器
docker run -d -p 8000:8000 --name python-test python-extraction:v1.0
# 测试健康检查
curl http://localhost:8000/api/health
# 应该返回:
# {
# "status": "healthy",
# "checks": {...}
# }
# 停止容器
docker stop python-test
docker rm python-test
```
#### 推送到ACR
```bash
# 打标签
docker tag python-extraction:v1.0 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0
# 推送镜像
docker push \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0
# 等待推送完成约5-10分钟镜像约1.1GB
# The push refers to repository [...]
# v1.0: digest: sha256:... size: ...
```
---
### 3.2 部署到SAE15分钟
**登录SAE控制台**https://sae.console.aliyun.com/
#### 创建命名空间(首次)
1. 进入【命名空间】
2. 点击【创建命名空间】:
```yaml
命名空间ID: cn-beijing:test-airesearch
命名空间名称: 测试环境
```
#### 创建应用
1. 点击【创建应用】
2. 应用基本信息:
```yaml
应用名称: python-extraction-test
命名空间: cn-beijing:test-airesearch
# 实例规格
CPU: 1核
内存: 2GB
实例数: 1
# 应用部署方式
部署方式: 镜像
镜像类型: 容器镜像服务企业版/个人版
```
3. 选择镜像:
```yaml
地域: 华北2北京
命名空间: ai-clinical
仓库: python-extraction
镜像版本: v1.0
# ⚠️ 使用VPC地址SAE内网拉取免流量费
镜像地址会自动转为VPC地址
crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0
```
4. 配置镜像访问凭证:
```yaml
用户名: gofeng117@163.com
密码: fengzhibo117
```
5. 应用配置:
```yaml
# 启动命令配置
启动命令: 留空使用Dockerfile的CMD
# 端口配置
容器端口: 8000
协议: TCP
```
6. 环境变量(可选):
```bash
LOG_LEVEL=INFO
TEMP_DIR=/tmp/extraction_service
```
7. 网络配置:
```yaml
VPC: ai-clinical-vpc
交换机: ai-clinical-vsw-f
安全组: ai-clinical-sg
```
8. 健康检查:
```yaml
# 存活检查Liveness
检查方式: HTTP
检查路径: /api/health
端口: 8000
初始延迟: 30秒
检查间隔: 10秒
检查超时: 5秒
不健康阈值: 3次
# 就绪检查Readiness
检查方式: HTTP
检查路径: /api/health
端口: 8000
初始延迟: 10秒
```
9. 点击【确认创建】
#### 等待部署完成
- 查看【实例部署】页面
- 状态变为【Running】约5-10分钟
- 记录内网地址:`http://172.17.173.66:8000`
#### 验证部署
```bash
# 方法1在SAE应用内查看日志
# 应该看到:
# INFO: Uvicorn running on http://0.0.0.0:8000
# INFO: Application startup complete
# 方法2从Node.js应用测试部署后
curl http://172.17.173.66:8000/api/health
```
---
## 🟢 四、Node.js后端部署50分钟
### 4.1 准备工作10分钟
#### 生成强JWT密钥
```bash
# 在PowerShell或Bash中生成
openssl rand -hex 32
# 或
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# 示例输出(使用您自己生成的):
# 8a3f9e7c2d1b5a4e6f8c9d0a3b5e7f1c2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4
```
#### 准备环境变量清单
创建文件 `backend/.env.production`不提交到Git
```bash
# ==================== 基础配置 ====================
NODE_ENV=production
PORT=3001
LOG_LEVEL=info
# ==================== 数据库连接 ====================
DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research?connection_limit=18&pool_timeout=10
# ==================== Python微服务 ⚠️ 关键!====================
EXTRACTION_SERVICE_URL=http://172.17.173.66:8000
# ==================== OSS对象存储 ====================
OSS_ACCESS_KEY_ID=LTAI5tB2Dt3NdvBL3G7nYGv7
OSS_ACCESS_KEY_SECRET=1iSN9k39RkApP93QjUhC1DcPIeMG4V
OSS_BUCKET=ai-clinical-research
OSS_ENDPOINT=oss-cn-beijing-internal.aliyuncs.com
OSS_REGION=cn-beijing
# ==================== JWT认证 ====================
JWT_SECRET=8a3f9e7c2d1b5a4e6f8c9d0a3b5e7f1c2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4
JWT_EXPIRES_IN=7d
# ==================== LLM API密钥 ====================
DEEPSEEK_API_KEY=sk-7f8cc37a79fa4799860b38fc7ba2e150
DASHSCOPE_API_KEY=sk-75b4ff29a14a49e79667a331034f3298
# ==================== CloseAI配置 ====================
CLOSEAI_API_KEY=sk-cu0iepbXYGGx2jc7BqP6ogtSWmP6fk918qV3RUdtGC3Ed1po
CLOSEAI_OPENAI_BASE_URL=https://api.openai-proxy.org/v1
CLOSEAI_CLAUDE_BASE_URL=https://api.openai-proxy.org/anthropic
# ==================== Dify配置 ====================
DIFY_API_URL=http://localhost/v1
DIFY_API_KEY=dataset-mfvdiKvQ213NvxWm7RoYMN3c
# ==================== Postgres-Only架构 ====================
QUEUE_TYPE=pgboss
CACHE_TYPE=postgres
```
---
### 4.2 构建Docker镜像30分钟
#### 方案选择
我们使用**方案B本地编译 + Docker打包**(最稳定)
#### 步骤1本地编译TypeScript
```bash
cd AIclinicalresearch/backend
# 安装依赖
npm install
# 编译TypeScript
npm run build
# 验证编译结果
ls dist/
# 应该看到index.js, common/, modules/ 等
```
#### 步骤2检查Dockerfile
确认Dockerfile内容正确
```dockerfile
FROM node:22-alpine
WORKDIR /app
# 复制package.json和package-lock.json
COPY package*.json ./
# 只安装生产依赖
RUN npm ci --only=production --ignore-scripts
# 复制编译后的代码
COPY dist ./dist
# 复制Prisma客户端
COPY node_modules/.prisma ./node_modules/.prisma
# 复制Prisma schema用于runtime
COPY prisma ./prisma
# ⚠️ 复制config目录重要
COPY config ./config
# 暴露端口
EXPOSE 3001
# 启动命令
CMD ["node", "dist/index.js"]
```
**⚠️ 关键修复1**:必须包含 `COPY config ./config`,否则会报错 `ENOENT: no such file or directory, open '/app/config/agents.yaml'`
#### 步骤3构建镜像
```bash
# 构建镜像
docker build -t backend-service:v1.3 .
# 等待构建完成约5分钟
```
#### 步骤4本地测试推荐
```bash
# 运行容器(连接本地数据库测试)
docker run -d -p 3001:3001 \
-e NODE_ENV=production \
-e DATABASE_URL="postgresql://postgres:postgres@host.docker.internal:5432/ai_clinical_research" \
-e EXTRACTION_SERVICE_URL=http://host.docker.internal:8000 \
--name backend-test \
backend-service:v1.3
# 查看日志
docker logs -f backend-test
# 应该看到:
# ✅ Loaded 12 agent configurations
# ✅ 数据库连接成功
# 🚀 AI临床研究平台 - 后端服务器启动成功!
# 📍 服务地址: http://localhost:3001
# 测试健康检查
curl http://localhost:3001/health
# 停止测试容器
docker stop backend-test
docker rm backend-test
```
#### 步骤5推送到ACR
```bash
# 打标签
docker tag backend-service:v1.3 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3
# 推送镜像
docker push \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3
# 等待推送完成约10分钟镜像约838MB
```
---
### 4.3 部署到SAE10分钟
**登录SAE控制台**https://sae.console.aliyun.com/
#### 创建应用
1. 点击【创建应用】
2. 应用基本信息:
```yaml
应用名称: nodejs-backend-test
命名空间: cn-beijing:test-airesearch
# 实例规格
CPU: 1核
内存: 2GB
实例数: 1
```
3. 选择镜像:
```yaml
镜像类型: 容器镜像服务企业版/个人版
地域: 华北2北京
命名空间: ai-clinical
仓库: backend-service
镜像版本: v1.3
# 镜像访问凭证
用户名: gofeng117@163.com
密码: fengzhibo117
```
4. 应用配置:
```yaml
# 启动命令
启动命令: 留空使用Dockerfile的CMD
# ⚠️ 关键:不要配置 /bin/bashAlpine Linux没有bash
# 端口配置
容器端口: 3001
协议: TCP
```
5. 环境变量(⚠️ 非常重要!):
**复制上面准备的完整环境变量清单**,特别注意:
```bash
# ⚠️ 最容易出错的环境变量
EXTRACTION_SERVICE_URL=http://172.17.173.66:8000
# 不是 PYTHON_SERVICE_URL名字必须正确
DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research?connection_limit=18&pool_timeout=10
# 注意:@ 要写成 %40
```
6. 网络配置:
```yaml
VPC: ai-clinical-vpc
交换机: ai-clinical-vsw-f
安全组: ai-clinical-sg
```
7. 健康检查:
```yaml
# 存活检查Liveness
检查方式: HTTP
检查路径: /health
端口: 3001
初始延迟: 60秒 # Node.js启动较慢
检查间隔: 10秒
# 就绪检查Readiness
检查方式: HTTP
检查路径: /health
端口: 3001
初始延迟: 30秒
```
8. 点击【确认创建】
#### 等待部署完成
- 查看【实例部署】页面
- 状态变为【Running】约10分钟
- 记录内网地址:`http://172.17.173.73:3001`
#### 验证部署
查看日志,确认以下信息:
```bash
# ✅ 应该看到的日志:
✅ Loaded 12 agent configurations
[PgBossQueue] Using PgBossQueue (Postgres-Only架构)
[PostgresCacheAdapter] Cleanup task started
✅ 数据库连接成功!
📊 数据库版本: PostgreSQL 15.14
PythonExecutorService initialized: http://172.17.173.66:8000 # ⚠️ 确认这个!
🚀 AI临床研究平台 - 后端服务器启动成功!
📍 服务地址: http://localhost:3001
Server listening at http://172.17.173.73:3001
# ❌ 如果看到错误:
ENOENT: no such file or directory, open '/app/config/agents.yaml'
→ Dockerfile缺少 COPY config ./config
Error: unable to determine transport target for "pino-pretty"
→ src/index.ts 日志配置问题,需要条件判断环境
ReferenceError: require is not defined
→ healthCheck.ts 使用了require需改为import
```
---
### 4.4 常见问题修复
#### 问题1config目录缺失
**错误**
```
ENOENT: no such file or directory, open '/app/config/agents.yaml'
```
**解决**
```dockerfile
# 在Dockerfile中添加
COPY config ./config
```
#### 问题2pino-pretty生产环境报错
**错误**
```
Error: unable to determine transport target for "pino-pretty"
```
**解决**:修改 `src/index.ts`
```typescript
const fastify = Fastify({
logger: config.nodeEnv === 'production'
? { level: config.logLevel } // 生产环境简单JSON日志
: { // 开发环境pino-pretty
level: config.logLevel,
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname',
},
},
},
});
```
#### 问题3healthCheck require报错
**错误**
```
ReferenceError: require is not defined in ES module
```
**解决**:修改 `src/common/health/healthCheck.ts`
```typescript
import os from 'os'; // 添加导入
// 修改使用方式
checks.cpu = {
usage: process.cpuUsage(),
loadAverage: process.platform !== 'win32' ? os.loadavg() : 'N/A' // 使用import的os
}
```
#### 问题4bash路径错误
**错误**
```
executable '/bin/bash' not found in $PATH
```
**解决**
- SAE启动命令留空使用Dockerfile的CMD
- 或使用 `/bin/sh` 代替 `/bin/bash`
---
## 🎨 五、前端Nginx部署30分钟
### 5.1 构建Docker镜像15分钟
#### 进入目录
```bash
cd AIclinicalresearch/frontend-v2
```
#### 检查关键文件
**1. Dockerfile**(多阶段构建):
```dockerfile
# 第一阶段构建React应用
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 第二阶段Nginx托管
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/templates/nginx.conf.template
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
EXPOSE 80
ENTRYPOINT ["/docker-entrypoint.sh"]
```
**2. docker-entrypoint.sh**(动态配置):
```bash
#!/bin/bash
set -e
# ⚠️ 检查必需的环境变量
if [ -z "$BACKEND_SERVICE_HOST" ]; then
echo "❌ ERROR: BACKEND_SERVICE_HOST environment variable is required!"
exit 1
fi
if [ -z "$BACKEND_SERVICE_PORT" ]; then
export BACKEND_SERVICE_PORT=3001 # 默认值
fi
# 使用envsubst动态替换配置
envsubst '${BACKEND_SERVICE_HOST} ${BACKEND_SERVICE_PORT}' \
< /etc/nginx/templates/nginx.conf.template \
> /etc/nginx/nginx.conf
# 启动Nginx
exec nginx -g 'daemon off;'
```
**3. nginx.conf**(使用变量占位符):
```nginx
upstream backend {
server ${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT} fail_timeout=30s max_fails=3;
keepalive 32;
}
server {
listen 80;
root /usr/share/nginx/html;
# API反向代理
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# ...
}
# SPA路由支持
location / {
try_files $uri $uri/ /index.html;
}
}
```
#### 构建镜像
```bash
# 构建镜像
docker build -t ai-clinical_frontend-nginx:v1.0 .
# 等待构建完成约10分钟
# 第一阶段会构建React应用第二阶段打包到Nginx
```
#### 本地测试
```bash
# 运行容器
docker run -d -p 3000:80 \
-e BACKEND_SERVICE_HOST=host.docker.internal \
-e BACKEND_SERVICE_PORT=3001 \
--name frontend-test \
ai-clinical_frontend-nginx:v1.0
# 访问前端
open http://localhost:3000
# 或
curl http://localhost:3000
# 停止容器
docker stop frontend-test
docker rm frontend-test
```
#### 推送到ACR
```bash
# 打标签
docker tag ai-clinical_frontend-nginx:v1.0 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0
# 推送镜像
docker push \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0
# 等待推送完成约3分钟镜像约50MB
```
---
### 5.2 部署到SAE15分钟
**登录SAE控制台**https://sae.console.aliyun.com/
#### 创建应用
1. 点击【创建应用】
2. 应用基本信息:
```yaml
应用名称: frontend-nginx-service
命名空间: cn-beijing:test-airesearch
# 实例规格
CPU: 0.5核
内存: 1GB
实例数: 1
```
3. 选择镜像:
```yaml
镜像类型: 容器镜像服务企业版/个人版
地域: 华北2北京
命名空间: ai-clinical
仓库: ai-clinical_frontend-nginx
镜像版本: v1.0
# 镜像访问凭证
用户名: gofeng117@163.com
密码: fengzhibo117
```
4. 应用配置:
```yaml
# 启动命令
启动命令: 留空使用ENTRYPOINT
# 端口配置
容器端口: 80
协议: TCP
```
5. 环境变量(⚠️ 关键配置):
```bash
BACKEND_SERVICE_HOST=172.17.173.73 # Node.js后端内网IP
BACKEND_SERVICE_PORT=3001
```
6. 网络配置:
```yaml
VPC: ai-clinical-vpc
交换机: ai-clinical-vsw-f
安全组: ai-clinical-sg
```
7. 健康检查:
```yaml
# 存活检查
检查方式: HTTP
检查路径: /health
端口: 80
初始延迟: 10秒
检查间隔: 10秒
# 就绪检查
检查方式: HTTP
检查路径: /health
端口: 80
初始延迟: 5秒
```
8. 点击【确认创建】
#### 等待部署完成
- 查看【实例部署】页面
- 状态变为【Running】约5分钟
- 记录内网地址:`http://172.17.173.72:80`
#### 验证部署
查看日志:
```bash
# ✅ 应该看到:
============================================
Starting Frontend Nginx Service
Backend Service: 172.17.173.73:3001
============================================
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```
---
## 🌐 六、CLB负载均衡配置10分钟
### 6.1 配置公网访问
**方式1SAE自动创建CLB推荐**
1. 进入SAE应用`frontend-nginx-service`
2. 点击【公网访问】或【访问配置】Tab
3. 点击【添加公网访问】
4. 配置参数:
```yaml
负载均衡类型: 公网
负载均衡产品: CLB (传统型负载均衡)
付费模式: 按量付费
# 监听配置
协议: HTTP
端口: 80
后端端口: 80
# 健康检查
健康检查: 启用
检查路径: /health
```
5. 点击【确定】
6. 等待2-3分钟自动分配公网IP
**方式2手动创建CLB**
1. 登录CLB控制台https://slb.console.aliyun.com/
2. 创建负载均衡实例
3. 配置监听器HTTP:80
4. 添加后端服务器前端Nginx的内网IP
5. 配置健康检查
### 6.2 获取公网地址
- 在SAE应用详情页查看【公网访问地址】
- 示例:`http://8.140.53.236/`
- 复制此地址用于测试
---
## ✅ 七、完整链路测试30分钟
### 7.1 基础功能测试
#### 测试1前端页面访问
```bash
# 浏览器访问
http://8.140.53.236/
# 应该看到:
✅ React应用正常加载
✅ 页面样式正常
✅ 没有CORS错误
```
#### 测试2健康检查
```bash
# 后端健康检查(通过前端代理)
curl http://8.140.53.236/api/v1/health
# 或
curl http://172.17.173.73:3001/health
# 应该返回:
{
"status": "ok",
"timestamp": "...",
"services": {
"database": "connected",
"cache": "available",
"queue": "running"
}
}
```
#### 测试3Python服务连接
```bash
# 直接测试Python服务
curl http://172.17.173.66:8000/api/health
# 应该返回:
{
"status": "healthy",
"checks": {
"pymupdf": {"available": true, "version": "1.26.7"},
...
}
}
```
---
### 7.2 业务功能测试
#### 测试1用户登录
1. 访问 http://8.140.53.236/
2. 输入用户名密码
3. 点击登录
4. 查看浏览器Network面板
```
Request URL: http://8.140.53.236/api/v1/auth/login
Status: 200 OK ✅
Response: { "token": "...", "user": {...} }
```
#### 测试2数据清洗模块工具C
1. 进入【数据清洗】→ 【工具C】
2. 上传Excel文件
3. 验证上传成功
4. 测试7大功能之一数值映射
- 选择列
- 配置映射规则
- 点击【执行映射】
- 查看结果
**关键验证**
```
浏览器Network面板
POST http://8.140.53.236/api/v1/dc/tool-c/quick-action
Status: 200 OK ✅
后端日志:
[QuickActionService] 调用重编码API: 性别
PythonExecutorService initialized: http://172.17.173.66:8000 ✅
[QuickActionService] 重编码成功 ✅
```
#### 测试3文献筛查模块ASL
1. 进入【文献筛查】模块
2. 创建项目
3. 上传文献
4. 执行智能筛查
5. 验证结果
---
### 7.3 性能测试
#### 响应时间检查
```bash
# 使用curl测试响应时间
curl -w "@-" -o /dev/null -s http://8.140.53.236/ <<'EOF'
time_namelookup: %{time_namelookup}\n
time_connect: %{time_connect}\n
time_appconnect: %{time_appconnect}\n
time_pretransfer: %{time_pretransfer}\n
time_redirect: %{time_redirect}\n
time_starttransfer: %{time_starttransfer}\n
----------\n
time_total: %{time_total}\n
EOF
# 期望结果:
# time_total < 1秒首次访问
# time_total < 0.3秒(后续访问)
```
---
## 📊 八、部署成果总结
### 8.1 已部署服务清单
| 服务 | 状态 | 内网地址 | 公网访问 |
|------|------|---------|---------|
| RDS PostgreSQL | ✅ | pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432 | ❌ |
| Python微服务 | ✅ | 172.17.173.66:8000 | ❌ |
| Node.js后端 | ✅ | 172.17.173.73:3001 | ❌ |
| 前端Nginx | ✅ | 172.17.173.72:80 | ✅ |
| CLB负载均衡 | ✅ | - | http://8.140.53.236/ |
### 8.2 关键配置速查
#### Python微服务环境变量
```bash
LOG_LEVEL=INFO
TEMP_DIR=/tmp/extraction_service
```
#### Node.js后端关键环境变量
```bash
NODE_ENV=production
PORT=3001
DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research
EXTRACTION_SERVICE_URL=http://172.17.173.66:8000 # ⚠️ 关键不是PYTHON_SERVICE_URL
```
#### 前端Nginx关键环境变量
```bash
BACKEND_SERVICE_HOST=172.17.173.73 # Node.js后端内网IP
BACKEND_SERVICE_PORT=3001
```
---
## ⚠️ 九、关键经验与注意事项
### 9.1 环境变量名必须精确
**问题**工具C的7大功能全部报错
```
connect ECONNREFUSED 127.0.0.1:8000
```
**原因**Node.js代码使用 `EXTRACTION_SERVICE_URL`但SAE配置了 `PYTHON_SERVICE_URL`
**解决**
```bash
# ❌ 错误
PYTHON_SERVICE_URL=http://172.17.173.66:8000
# ✅ 正确
EXTRACTION_SERVICE_URL=http://172.17.173.66:8000
```
**教训**:环境变量名必须与代码完全一致,一个字母都不能错!
---
### 9.2 "重启应用" vs "部署应用"
**问题**:点击"部署应用"导致IP地址变更
| 操作 | 用途 | IP是否变 | 何时使用 |
|------|------|---------|---------|
| **重启应用** | 重启容器 | ❌ 不会 | 修改环境变量后 |
| **部署应用** | 更新镜像 | ✅ 会变 | 更新代码/镜像时 |
**教训**
- 只修改环境变量 → 用"重启应用"
- 更新代码/镜像 → 用"部署应用"
---
### 9.3 Dockerfile必须包含config目录
**问题**
```
ENOENT: no such file or directory, open '/app/config/agents.yaml'
```
**解决**
```dockerfile
# ✅ 必须添加
COPY config ./config
```
---
### 9.4 pino-pretty仅用于开发环境
**问题**
```
Error: unable to determine transport target for "pino-pretty"
```
**原因**`pino-pretty`是devDependencies生产环境没有安装
**解决**:条件判断环境
```typescript
logger: config.nodeEnv === 'production'
? { level: config.logLevel }
: { level: config.logLevel, transport: { target: 'pino-pretty', ... } }
```
---
### 9.5 ES Module兼容性
**问题**
```
ReferenceError: require is not defined in ES module
```
**解决**
```typescript
// ❌ 错误
require('os').loadavg()
// ✅ 正确
import os from 'os';
os.loadavg()
```
---
### 9.6 Alpine Linux没有bash
**问题**
```
executable '/bin/bash' not found in $PATH
```
**解决**
- SAE启动命令留空
- 或使用 `/bin/sh` 代替
---
### 9.7 数据库URL中的@符号
**格式**
```bash
# ✅ 正确URL编码
DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-xxx.pg.rds.aliyuncs.com:5432/ai_clinical_research
# ❌ 错误(未编码)
DATABASE_URL=postgresql://airesearch:Xibahe@fengzhibo117@pgm-xxx.pg.rds.aliyuncs.com:5432/ai_clinical_research
```
**规则**:密码中的 `@` 必须编码为 `%40`
---
### 9.8 使用VPC镜像地址SAE拉取
**SAE部署时选择镜像**
```bash
# ✅ 正确VPC地址免流量费
crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3
# ❌ 不推荐(公网地址,收流量费)
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3
```
**规则**
- 本地推送镜像 → 使用公网地址
- SAE拉取镜像 → 使用VPC地址
---
### 9.9 健康检查初始延迟
**不同服务的启动时间**
| 服务 | 启动时间 | 初始延迟建议 |
|------|---------|-------------|
| Python微服务 | 10秒 | 30秒 |
| Node.js后端 | 30秒 | 60秒 |
| 前端Nginx | 5秒 | 10秒 |
**教训**Node.js启动较慢需要更长的初始延迟
---
### 9.10 前端动态配置后端地址
**架构优势**
- 前端使用环境变量 `BACKEND_SERVICE_HOST`
- 通过 `envsubst` 在容器启动时动态注入
- 后端IP变更时只需重启前端应用无需重新构建镜像
**关键文件**
- `docker-entrypoint.sh`:动态替换配置
- `nginx.conf`:使用 `${BACKEND_SERVICE_HOST}` 占位符
---
## 🚀 十、未来优化建议
### 10.1 使用服务发现代替IP地址
**当前配置**使用IP
```bash
BACKEND_SERVICE_HOST=172.17.173.73
EXTRACTION_SERVICE_URL=http://172.17.173.66:8000
```
**优化方案**(使用服务名):
```bash
BACKEND_SERVICE_HOST=nodejs-backend-test.cn-beijing:test-airesearch.svc.cluster.local
EXTRACTION_SERVICE_URL=http://python-extraction-test.cn-beijing:test-airesearch.svc.cluster.local:8000
```
**优点**
- ✅ IP变更不影响通信
- ✅ 自动负载均衡
- ✅ 更稳定可靠
---
### 10.2 配置HTTPS
**步骤**
1. 申请域名
2. 申请SSL证书阿里云免费证书或Let's Encrypt
3. 在CLB配置HTTPS监听端口443
4. 上传SSL证书
5. 配置HTTP自动跳转HTTPS
---
### 10.3 配置自动扩缩容
**SAE弹性伸缩**
```yaml
# 根据CPU使用率自动扩缩容
最小实例数: 1
最大实例数: 3
目标CPU使用率: 70%
```
**适用场景**
- 流量波动大
- 高峰期需要更多实例
- 低峰期节约成本
---
### 10.4 配置日志分析
**阿里云SLS日志服务**
- 自动收集SAE日志
- 实时查询和分析
- 配置告警规则
---
### 10.5 配置监控告警
**云监控配置**
```yaml
CPU使用率 > 80% → 告警
内存使用率 > 80% → 告警
健康检查失败 → 告警
错误日志增多 → 告警
```
---
## 📝 十一、快速命令参考
### 11.1 Docker镜像管理
```bash
# 登录ACR
docker login --username=gofeng117@163.com \
--password=fengzhibo117 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
# 构建并推送Python镜像
cd AIclinicalresearch/extraction_service
docker build -t python-extraction:v1.0 .
docker tag python-extraction:v1.0 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0
# 构建并推送Node.js镜像
cd ../backend
npm run build
docker build -t backend-service:v1.3 .
docker tag backend-service:v1.3 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3
# 构建并推送前端镜像
cd ../frontend-v2
docker build -t ai-clinical_frontend-nginx:v1.0 .
docker tag ai-clinical_frontend-nginx:v1.0 \
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0
```
---
### 11.2 数据库连接
```bash
# 连接到RDS临时开启外网
docker exec -e PGPASSWORD="Xibahe@fengzhibo117" \
ai-clinical-postgres psql \
-h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \
-p 5432 -U airesearch -d ai_clinical_research
# 查看Schema列表
docker exec -e PGPASSWORD="Xibahe@fengzhibo117" \
ai-clinical-postgres psql \
-h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \
-p 5432 -U airesearch -d ai_clinical_research \
-c "SELECT nspname FROM pg_namespace WHERE nspname LIKE '%_schema';"
```
---
### 11.3 健康检查
```bash
# Python服务
curl http://172.17.173.66:8000/api/health
# Node.js后端
curl http://172.17.173.73:3001/health
# 前端Nginx
curl http://172.17.173.72:80/health
# 公网访问
curl http://8.140.53.236/
```
---
## 🎉 十二、部署完成检查清单
### 最终验证
- [ ] ✅ Python微服务健康检查通过
- [ ] ✅ Node.js后端健康检查通过
- [ ] ✅ 前端Nginx健康检查通过
- [ ] ✅ 公网地址可以访问
- [ ] ✅ 用户可以正常登录
- [ ] ✅ 文献筛查功能正常
- [ ] ✅ 数据清洗工具C的7大功能正常
- [ ] ✅ 文件上传功能正常
- [ ] ✅ AI对话功能正常
- [ ] ✅ 没有CORS错误
- [ ] ✅ 没有502/504错误
- [ ] ✅ 响应时间 < 1秒
### 文档更新
- [ ] 更新 `00-部署进度总览.md` 中的内网IP地址
- [ ] 记录公网访问地址
- [ ] 记录遇到的问题和解决方案
- [ ] 更新环境变量清单
---
## 📞 十三、技术支持
### 常见问题排查
**问题1工具C功能报错 "connect ECONNREFUSED 127.0.0.1:8000"**
- 检查Node.js环境变量 `EXTRACTION_SERVICE_URL`
- 确保值为 `http://172.17.173.66:8000`
- 重启Node.js应用
**问题2前端访问后端报502错误**
- 检查前端环境变量 `BACKEND_SERVICE_HOST`
- 确保值为Node.js后端的内网IP
- 重启前端应用
**问题3SAE应用启动失败**
- 查看实例日志,找到具体错误信息
- 参考本文档第9节"关键经验与注意事项"
- 对照检查Dockerfile和环境变量
---
## 🎯 总结
恭喜您已经完成了AI临床研究平台的完整部署
**部署成果**
- ✅ 4个服务全部成功部署Python、Node.js、前端、数据库
- ✅ 所有功能正常运行
- ✅ 公网可以访问
- ✅ 生产环境就绪
**部署时间**
- 预计时间3.5小时
- 实际时间约6小时包含问题排查
**关键经验**
- 环境变量名必须精确匹配
- 区分"重启应用"和"部署应用"
- Dockerfile必须包含所有必需文件
- 使用VPC地址拉取镜像
- 健康检查初始延迟要足够
**下一步**
- 配置HTTPS
- 绑定域名
- 配置监控告警
- 优化性能
- 配置自动备份
---
> **文档维护**本文档基于2025-12-25实际部署经历编写请根据实际情况更新
> **最后更新**2025-12-25
> **部署状态**:✅ 完全成功