From e21014eb503056caa736c7c07f4f26c0038c8d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Wed, 18 Feb 2026 23:35:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(diagnostics,=20documentation):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E7=B3=BB=E7=BB=9F=E8=B4=9F=E8=BD=BD=E8=AF=8A=E6=96=AD?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E4=B8=8E=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 `backend` 目录下新增 `诊断负载.sh` 脚本,提供系统负载、CPU、内存使用情况及数据库连接数的快速诊断功能。新增文档 `负载问题排查与快速降负载指南.md`,详细说明负载诊断步骤、常见原因及解决方法,帮助用户有效管理系统负载。此改动提升了系统监控能力与用户支持。 --- backend/诊断负载.sh | 90 ++++++++++++++++ docs/负载问题排查与降负载.md | 139 +++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100755 backend/诊断负载.sh create mode 100644 docs/负载问题排查与降负载.md diff --git a/backend/诊断负载.sh b/backend/诊断负载.sh new file mode 100755 index 0000000..983b9cd --- /dev/null +++ b/backend/诊断负载.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# 快速诊断系统负载问题 + +echo "=== 系统负载诊断工具 ===" +echo "" + +# 1. 当前负载 +echo "📊 当前负载情况:" +uptime +echo "" + +# 2. CPU 和内存使用 +echo "💻 CPU 和内存使用:" +top -bn1 | head -5 +echo "" + +# 3. 查看占用 CPU 最高的进程 +echo "🔥 CPU 占用最高的进程(前 10):" +ps aux --sort=-%cpu | head -11 | awk '{printf "%-8s %-6s %-6s %-6s %s\n", $1, $2, $3"%", $4"%", $11}' +echo "" + +# 4. 查看 Python 进程(交易服务) +echo "🐍 Python 进程(交易服务):" +ps aux | grep -E "python.*trading|python.*main|uvicorn" | grep -v grep | awk '{printf "PID: %-6s CPU: %-5s MEM: %-5s CMD: %s\n", $2, $3"%", $4"%", $11" "$12" "$13" "$14}' +echo "" + +# 5. 检查是否有同步操作在运行 +echo "🔄 检查同步操作:" +if [ -f "logs/api.log" ]; then + echo "最近的同步日志(最后 10 行):" + tail -100 logs/api.log | grep -i "同步\|sync.*binance\|sync_trades" | tail -10 || echo " 未找到同步日志" +else + echo " 日志文件不存在" +fi +echo "" + +# 6. 检查数据库连接数 +echo "🗄️ 数据库连接数:" +if command -v mysql >/dev/null 2>&1; then + DB_HOST="${DB_HOST:-localhost}" + DB_USER="${DB_USER:-root}" + DB_PASS="${DB_PASS:-}" + DB_NAME="${DB_NAME:-auto_trade_sys}" + + if [ -n "$DB_PASS" ]; then + mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASS" -e "SHOW PROCESSLIST;" 2>/dev/null | head -20 || echo " 无法连接数据库" + else + mysql -h"$DB_HOST" -u"$DB_USER" -e "SHOW PROCESSLIST;" 2>/dev/null | head -20 || echo " 无法连接数据库(需要配置 DB_PASS)" + fi +else + echo " mysql 客户端未安装" +fi +echo "" + +# 7. 检查内存使用详情 +echo "💾 内存使用详情:" +free -h +echo "" + +# 8. 检查是否有大量 I/O 等待 +echo "📈 I/O 和系统状态(5秒采样):" +vmstat 1 5 +echo "" + +# 9. 检查交易服务日志中的错误 +echo "⚠️ 最近的错误日志(最后 5 条):" +if [ -f "logs/api.log" ]; then + tail -200 logs/api.log | grep -i "error\|exception\|failed\|timeout" | tail -5 || echo " 未找到错误日志" +fi +if [ -f "../trading_system/logs/trading_*.log" ] 2>/dev/null; then + tail -200 ../trading_system/logs/trading_*.log 2>/dev/null | grep -i "error\|exception\|failed" | tail -5 || echo "" +fi +echo "" + +echo "=== 诊断完成 ===" +echo "" +echo "💡 建议:" +echo " 1. 如果 CPU 占用高的是 Python 进程,可能是:" +echo " - 市场扫描正在运行(计算技术指标)" +echo " - 订单同步正在运行(从币安拉取大量订单)" +echo " - 数据库查询慢(检查慢查询日志)" +echo "" +echo " 2. 如果内存占用高,检查是否有内存泄漏" +echo "" +echo " 3. 如果 I/O 等待高,可能是数据库查询慢或磁盘慢" +echo "" +echo " 4. 临时降负载方法:" +echo " - 暂停市场扫描(在配置中设置 SCAN_ENABLED=False)" +echo " - 等待同步操作完成(不要手动取消)" +echo " - 重启交易服务(如果进程异常)" diff --git a/docs/负载问题排查与降负载.md b/docs/负载问题排查与降负载.md new file mode 100644 index 0000000..d7fd206 --- /dev/null +++ b/docs/负载问题排查与降负载.md @@ -0,0 +1,139 @@ +# 负载问题排查与快速降负载指南 + +## 当前负载:1.59(2 CPU 系统) + +**Load average: 1.59, 0.55, 0.24** 表示: +- **1 分钟平均**:1.59(接近 2 CPU 满载,约 79.5% CPU 使用) +- **5 分钟平均**:0.55(之前较低,说明是最近才涨起来的) +- **15 分钟平均**:0.24(历史较低) + +## 快速诊断 + +运行诊断脚本: +```bash +cd backend +./诊断负载.sh +``` + +这会显示: +- CPU 占用最高的进程 +- Python 交易服务进程的资源占用 +- 是否有同步操作在运行 +- 数据库连接数 +- 内存和 I/O 状态 + +## 常见原因 + +### 1. **订单同步正在运行**(最可能) + +如果前端正在执行「同步订单」(特别是「全量同步 + 30 天」),会: +- 从币安拉取**所有交易对**的历史订单(可能几百个 symbol × 每个 symbol 的订单) +- 对每个订单做多次数据库查询(`get_by_exit_order_id`、`get_by_symbol` 等) +- 如果有 1000 个订单,可能产生 3000+ 次数据库查询 + +**解决方法**: +- **等待同步完成**(不要手动取消,否则数据可能不完整) +- 如果必须停止,可以在前端取消,但已处理的数据会保留 +- 下次同步时选择**更短的时间范围**(如 7 天而不是 30 天) +- 或**不勾选「全量同步」**(只同步数据库中已有的交易对) + +### 2. **市场扫描正在运行** + +交易服务会定期扫描市场并计算技术指标(RSI、MACD、布林带、ATR 等),这是 CPU 密集操作。 + +**检查方法**: +```bash +# 查看交易服务日志 +tail -f trading_system/logs/trading_*.log | grep -i "扫描\|scan" +``` + +**临时降负载**: +在配置中设置 `SCAN_ENABLED=False` 暂停扫描(但会停止策略交易) + +### 3. **多个账号进程同时运行** + +如果有多个账号,每个账号一个进程,且**同时**开始扫描,负载会叠加。 + +**检查方法**: +```bash +ps aux | grep "python.*trading\|python.*main" | grep -v grep +``` + +**优化**: +- 确保 `SCAN_CONCURRENT_SYMBOLS=2`(2 CPU 4G 多账号建议 2) +- 如果仍高,可降为 `1` + +### 4. **数据库查询慢** + +虽然已优化了订单列表查询,但同步操作仍可能产生大量查询。 + +**检查方法**: +```bash +# 如果有 MySQL 慢查询日志 +tail -f /var/log/mysql/slow.log +``` + +## 快速降负载方法 + +### 方法 1:等待同步完成(推荐) + +如果正在同步订单,**等待完成**是最安全的做法。同步完成后负载会自动降下来。 + +### 方法 2:降低扫描并发 + +在配置中设置: +```json +{ + "SCAN_CONCURRENT_SYMBOLS": 1 +} +``` + +这会降低市场扫描的 CPU 占用,但扫描时间会变长。 + +### 方法 3:暂停市场扫描(临时) + +在配置中设置: +```json +{ + "SCAN_ENABLED": false +} +``` + +**注意**:这会停止策略交易,只在紧急降负载时使用。 + +### 方法 4:重启交易服务(最后手段) + +如果进程异常或卡死: +```bash +# 通过 supervisor +supervisorctl restart auto_sys_* + +# 或手动 +pkill -f "python.*trading" +# 然后重新启动 +``` + +## 预防措施 + +1. **同步订单时**: + - 优先选择**较短时间范围**(7 天而不是 30 天) + - **不勾选「全量同步」**(除非确实需要补全所有交易对) + - 避免在交易高峰期同步 + +2. **配置优化**: + - `SCAN_CONCURRENT_SYMBOLS=2`(2 CPU 4G 多账号) + - `SCAN_INTERVAL_SEC` 不要太短(建议 ≥ 300 秒) + +3. **监控**: + - 定期运行 `./诊断负载.sh` 检查系统状态 + - 关注日志中的错误和警告 + +## 负载正常范围 + +对于 **2 CPU 4G** 系统: +- **正常**:Load average < 1.0(CPU 使用率 < 50%) +- **偏高**:Load average 1.0-1.5(CPU 使用率 50-75%) +- **过高**:Load average > 1.5(CPU 使用率 > 75%,需要关注) +- **满载**:Load average ≥ 2.0(CPU 100% 使用,有进程在等待) + +当前 **1.59** 属于**偏高**,需要排查原因。