# 甲辰藏品管理系统 部署手册 **当前版本:v1.2.88** --- ## 环境概览 ### 服务器信息 | 环境 | 前端 | 后端 | SSH密码 | |------|------|------|--------| | **D测试环境** | 114.55.137.168, 172.26.30.32 (内网) | 47.111.184.210, 172.26.30.33 (内网) | Jiachend123 | | **101生产环境** | 47.98.171.101 (80端口) | 47.98.171.101:8080 | Coolbot123 | ### 数据库信息 | 用途 | 数据库 | 地址 | 端口 | 用户名 | 密码 | |------|--------|------|------|--------|------| | **主数据库** | jiachenlong | pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com | 5432 | jiachenlong | Passwd1@3 | | **一尘数据库** | coolbot_data | pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com | 5432 | coolbot | Coolbot123 | > ⚠️ **密码中的特殊字符 `@` 必须URL编码为 `%40`** > - `Passwd1@3` → `Passwd1%403` > - `Coolbot123` 无需编码 ### OSS存储 - Bucket: jiachenlong-oss --- ## 环境变量 (.env) > 📁 完整示例见 `backend/.env.example` ### 数据库配置 ```env # 主数据库 - jiachenlong DATABASE_URL=postgresql://jiachenlong:Passwd1%403@pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com:5432/jiachenlong # 一尘数据库 - coolbot_data COOLBOT_DB_URL=postgresql://coolbot:Coolbot123@pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com:5432/coolbot_data ``` ### JWT认证配置 ```env SECRET_KEY=jiachenlong-production-secret-key-2026 ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=10080 ``` ### 阿里云百炼AI (DASHSCOPE) ```env # 用于AI批量解析藏品行情数据 DASHSCOPE_API_KEY=your-dashscope-api-key ``` ### 阿里云OSS存储 ```env OSS_ACCESS_KEY_ID=your-oss-access-key-id OSS_ACCESS_KEY_SECRET=your-oss-access-key-secret OSS_BUCKET=jiachenlong-oss OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com ``` ### 阿里云短信服务 ```env SMS_ACCESS_KEY_ID=your-sms-access-key-id SMS_ACCESS_KEY_SECRET=your-sms-access-key-secret SMS_SIGN_NAME=您的签名 SMS_TEMPLATE_CODE=SMS_xxx ``` ### 请求限流配置 ```env RATE_LIMIT_ENABLED=true RATE_LIMIT_SMS_PER_MINUTE=3 RATE_LIMIT_OCR_PER_MINUTE=10 RATE_LIMIT_BATCH_PER_MINUTE=5 RATE_LIMIT_API_PER_MINUTE=60 ``` ### 管理员账号 ```env ADMIN_USERNAME=admin ADMIN_PASSWORD=admin123 ``` --- ## 部署流程 ### 1. 获取代码 ```bash # 克隆仓库 git clone http://caibotd:Caibotd123@101.37.160.219/root/jiachenlong.git # 切换到目标版本 cd jiachenlong git checkout v1.2.88 # 或指定版本tag ``` ### 2. 构建前端 ```bash cd frontend npm install npm run build ``` ### 3. 配置后端环境变量 在后端服务器创建 `.env` 文件: ```bash cat > /root/jiachenlong/backend/.env << 'EOF' # 主数据库 - jiachenlong DATABASE_URL=postgresql://jiachenlong:Passwd1%403@pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com:5432/jiachenlong # 一尘数据库 - coolbot_data COOLBOT_DB_URL=postgresql://coolbot:Coolbot123@pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com:5432/coolbot_data # JWT SECRET_KEY=jiachenlong-production-secret-key-2026 ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=10080 # 阿里云百炼AI DASHSCOPE_API_KEY=your-dashscope-api-key # 阿里云OSS OSS_ACCESS_KEY_ID=your-oss-access-key-id OSS_ACCESS_KEY_SECRET=your-oss-access-key-secret OSS_BUCKET=jiachenlong-oss OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com # 阿里云SMS SMS_ACCESS_KEY_ID=your-sms-access-key-id SMS_ACCESS_KEY_SECRET=your-sms-access-key-secret SMS_SIGN_NAME=您的签名 SMS_TEMPLATE_CODE=SMS_xxx # 限流 RATE_LIMIT_ENABLED=true RATE_LIMIT_SMS_PER_MINUTE=3 RATE_LIMIT_OCR_PER_MINUTE=10 RATE_LIMIT_BATCH_PER_MINUTE=5 RATE_LIMIT_API_PER_MINUTE=60 # 管理员 ADMIN_USERNAME=admin ADMIN_PASSWORD=admin123 EOF ``` ### 4. 上传文件到服务器 ```bash # 上传前端 scp -r frontend/dist/* root@47.111.184.210:/var/www/html/ # 上传后端 scp -r backend/app root@47.111.184.210:/root/jiachenlong/backend/ scp backend/requirements.txt root@47.111.184.210:/root/jiachenlong/backend/ scp backend/.env root@47.111.184.210:/root/jiachenlong/backend/ ``` ### 5. 配置Nginx D测试环境配置示例 (`/etc/nginx/nginx.conf`): ```nginx user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; # 日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # Gzip压缩 gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml; server { listen 80; server_name _; # 前端静态文件 root /var/www/html; index index.html; # 大文件上传限制 client_max_body_size 50M; client_body_timeout 300s; # 前端静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 30d; add_header Cache-Control "public, immutable"; } # 前端 SPA 路由 location / { try_files $uri $uri/ /index.html; } # API代理到后端 location /api/ { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; proxy_connect_timeout 75s; } # 上传文件代理 location /uploads/ { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 静态文件服务 location /static/ { alias /var/www/html/static/; expires 30d; } } } ``` ### 6. 启动后端服务 ```bash # 激活conda环境 source /opt/conda/etc/profile.d/conda.sh conda activate py312 # 安装依赖(如需要) pip install -r requirements.txt # 创建日志目录 mkdir -p /root/jiachenlong/backend/logs # 设置Python路径 export PYTHONPATH=/root/jiachenlong/backend # 启动后端 cd /root/jiachenlong/backend nohup python -m uvicorn app.main:app --host 0.0.0.0 --port 3000 > logs/api.log 2>&1 & ``` ### 7. 重启Nginx ```bash # 测试配置 nginx -t # 重载配置 nginx -s reload # 或完全重启 killall nginx && nginx ``` --- ## SSL证书配置 (Let's Encrypt) ### 安装 Certbot ```bash # CentOS/RHEL yum install epel-release yum install certbot python3-certbot-nginx # 或使用 pip pip install certbot certbot-nginx ``` ### 获取证书 ```bash # 停止 Nginx(如果正在运行) nginx -s stop # 获取证书(单域名) certbot certonly --standalone -d jiachenlong.com --agree-tos --email admin@jiachenlong.com --no-eff-email # 获取证书(多域名) certbot certonly --standalone -d jiachenlong.com -d www.jiachenlong.com --agree-tos --email admin@jiachenlong.com --no-eff-email # 重启 Nginx nginx ``` ### 自动续期 ```bash # 测试续期(dry-run) certbot renew --dry-run # 设置定时任务(每天凌晨自动续期) crontab -e # 添加以下行: # 0 3 * * * certbot renew --quiet --deploy-hook "nginx -s reload" ``` ### Nginx HTTPS 配置 ```nginx server { listen 80; server_name jiachenlong.com www.jiachenlong.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name jiachenlong.com www.jiachenlong.com; # SSL证书 ssl_certificate /etc/letsencrypt/live/jiachenlong.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/jiachenlong.com/privkey.pem; # SSL安全配置 ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; add_header Strict-Transport-Security "max-age=63072000" always; # ... 其余配置同上 ... } ``` --- ## 数据库迁移 (Alembic) ### 查看当前版本 ```bash cd /root/jiachenlong/backend source /opt/conda/etc/profile.d/conda.sh && conda activate py312 export PYTHONPATH=/root/jiachenlong/backend alembic current ``` ### 查看迁移历史 ```bash alembic history --verbose ``` ### 创建新迁移 ```bash # 自动生成迁移脚本(根据模型变更) alembic revision --autogenerate -m "描述变更内容" # 手动创建空白迁移 alembic revision -m "描述变更内容" ``` ### 执行迁移 ```bash # 升级到最新版本 alembic upgrade head # 升级到指定版本 alembic upgrade # 检查是否有待执行迁移 alembic check ``` ### 回滚 ```bash # 回滚一步 alembic downgrade -1 # 回滚到初始状态 alembic downgrade base ``` ### 生产环境迁移流程 ```bash # 1. 在测试环境验证迁移 alembic upgrade head # 2. 检查数据完整性 # (在测试环境执行应用相关测试) # 3. 在生产环境执行迁移(建议在低峰期) alembic upgrade head # 4. 重启后端服务 pkill -f 'uvicorn app.main:app' nohup python -m uvicorn app.main:app --host 0.0.0.0 --port 3000 > logs/api.log 2>&1 & ``` --- ## 常见问题与解决方案 ### 1. 后端启动失败:`address already in use` **原因**:端口被占用 **解决**: ```bash # 查看占用进程 fuser 3000/tcp # 杀死占用进程 fuser -k 3000/tcp ``` ### 2. 后端启动失败:`ModuleNotFoundError: No module named 'xxx'` **原因**:Python依赖缺失 **解决**: ```bash pip install -r requirements.txt # 或安装特定依赖 pip install bcrypt passlib python-jose python-multipart email-validator oss2 Pillow ``` ### 3. API返回500错误:`name 'response' is not defined` **原因**:FastAPI函数参数中使用了`response: Response = None`,但该参数已被废弃或删除 **解决**:检查并修复 `app/routers/*.py` 文件中的 `response.headers` 使用 ```python # 找到类似代码 response.headers['X-Total-Pages'] = str(total_pages) # 删除这些行(它们不是必需的) ``` ### 4. 数据库连接失败:`could not translate host name` **原因**:主机名未正确解析 **解决**:确保 `.env` 中的数据库地址使用完整域名 ```bash # 错误 DB_HOST=pgm-bp1t5w248t7s1pvr # 正确 DB_HOST=pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com ``` ### 5. 数据库连接失败:密码中特殊字符问题 **原因**:密码中的 `@` 符号导致URL解析错误 **解决**:URL编码密码 ```bash # 密码 Passwd1@3 编码为 Passwd1%403 DATABASE_URL=postgresql://jiachenlong:Passwd1%403@... ``` ### 6. 前端403 Forbidden **原因**:文件权限问题 **解决**: ```bash chown -R nginx:nginx /var/www/html chmod -R 755 /var/www/html ``` ### 7. Nginx配置错误:`server directive is not allowed here` **原因**:nginx配置文件放在HTTP块外面 **解决**:确保server块在http块内部 ### 8. 前端显示旧版本 **原因**:浏览器缓存 **解决**:强制刷新 (Ctrl+Shift+R) 或清除缓存 ### 9. 后端日志显示数据库连接超时 **原因**:数据库地址不可达或网络问题 **解决**: ```bash # 测试连接 telnet pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com 5432 # 或 nc -zv pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com 5432 ``` ### 10. 文件上传失败 413 Request Entity Too Large **原因**:Nginx `client_max_body_size` 限制 **解决**:在 nginx.conf 的 http 或 server 块中添加: ```nginx client_max_body_size 50M; ``` --- ## 代码修改注意事项 ### information.py / collections.py 常见问题 1. **Response参数问题** - 函数签名中的 `response: Response = None` 会导致 `NameError` - 如果不需要修改响应头,应该直接删除这个参数 - 同时删除函数体内使用 `response.headers` 的代码 2. **处理方法**: ```python # 错误写法 def get_list(response: Response = None): response.headers['X-Total'] = '100' # 会报错 # 正确写法 def get_list(): # 不使用response.headers,或使用Response参数的正确方式 pass ``` ### collections.py 统计接口 - `get_current_user` 可能返回 `None` - 访问 `current_user.role` 前必须检查 `current_user` 是否为 `None` ```python # 错误 if current_user.role == "admin": # 正确 if not current_user or current_user.role != "admin": return {"totalCount": 0} ``` --- ## 改进建议(已完成) - [x] 使用 `python-dotenv` 管理环境变量 → `backend/.env.example` - [x] Alembic 数据库迁移管理 → `backend/alembic/` - [x] 单元测试框架 → `backend/tests/` - [ ] 自动化部署脚本 (deploy.sh) - [ ] CI/CD 自动化测试 - [ ] 健康检查端点 --- ## 快速命令参考 ```bash # ========== 后端管理 ========== # 查看后端进程 ps aux | grep uvicorn | grep -v grep # 查看后端日志 tail -f /root/jiachenlong/backend/logs/api.log # 重启后端 pkill -f 'uvicorn app.main:app' cd /root/jiachenlong/backend source /opt/conda/etc/profile.d/conda.sh && conda activate py312 export PYTHONPATH=/root/jiachenlong/backend nohup python -m uvicorn app.main:app --host 0.0.0.0 --port 3000 > logs/api.log 2>&1 & # ========== 测试API ========== curl http://localhost:3000/api/collections/stats curl http://localhost:3000/api/information/list?info_type=seek # ========== Nginx ========== nginx -t # 测试配置 nginx -s reload # 重载配置 nginx -s stop # 停止 killall nginx && nginx # 完全重启 # ========== 数据库迁移 ========== cd /root/jiachenlong/backend export PYTHONPATH=/root/jiachenlong/backend alembic current # 查看当前版本 alembic history # 查看历史 alembic upgrade head # 执行迁移 alembic downgrade -1 # 回滚一步 # ========== SSL证书 ========== certbot renew --dry-run # 测试续期 certbot renew --quiet # 执行续期 ``` --- *最后更新:2026-04-12*