智慧水务管理系统 - 精河县供水工程综合管理平台

run_all_benchmarks.sh 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #!/bin/bash
  2. #
  3. # 水务管理系统 - 统一性能压力测试入口脚本
  4. #
  5. # 依次运行:REST API / WebSocket / MQTT IoT / 数据库查询 四项压力测试,
  6. # 收集系统指标(CPU、内存、磁盘 IO),生成综合报告。
  7. #
  8. # 用法:
  9. # bash run_all_benchmarks.sh [--quick] [--output-dir DIR]
  10. #
  11. # --quick: 快速模式(减少测试时长,适合 CI/CD)
  12. # --output-dir: 结果输出目录(默认 ./reports/YYYYMMDD_HHMMSS)
  13. #
  14. set -euo pipefail
  15. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  16. cd "$SCRIPT_DIR"
  17. # ==================== 参数解析 ====================
  18. QUICK_MODE=false
  19. OUTPUT_DIR=""
  20. API_HOST="${API_HOST:-localhost}"
  21. API_PORT="${API_PORT:-8080}"
  22. WS_HOST="${WS_HOST:-localhost}"
  23. WS_PORT="${WS_PORT:-8765}"
  24. MQTT_BROKER="${MQTT_BROKER:-localhost}"
  25. MQTT_PORT="${MQTT_PORT:-1883}"
  26. DB_HOST="${DB_HOST:-localhost}"
  27. DB_PORT="${DB_PORT:-5432}"
  28. DB_NAME="${DB_NAME:-water_management}"
  29. DB_USER="${DB_USER:-postgres}"
  30. DB_PASS="${DB_PASS:-postgres}"
  31. while [[ $# -gt 0 ]]; do
  32. case $1 in
  33. --quick) QUICK_MODE=true; shift ;;
  34. --output-dir) OUTPUT_DIR="$2"; shift 2 ;;
  35. --api-host) API_HOST="$2"; shift 2 ;;
  36. --ws-host) WS_HOST="$2"; shift 2 ;;
  37. --mqtt-broker) MQTT_BROKER="$2"; shift 2 ;;
  38. --db-host) DB_HOST="$2"; shift 2 ;;
  39. *) echo "未知参数: $1"; exit 1 ;;
  40. esac
  41. done
  42. # 默认输出目录
  43. if [[ -z "$OUTPUT_DIR" ]]; then
  44. OUTPUT_DIR="./reports/$(date +%Y%m%d_%H%M%S)"
  45. fi
  46. mkdir -p "$OUTPUT_DIR"
  47. # ==================== 工具函数 ====================
  48. log() { echo "[$(date '+%H:%M:%S')] $*"; }
  49. error() { echo "[$(date '+%H:%M:%S')] ❌ $*" >&2; }
  50. check_python_deps() {
  51. log "检查 Python 依赖..."
  52. pip install -q -r requirements.txt 2>/dev/null || {
  53. error "依赖安装失败,请手动执行: pip install -r requirements.txt"
  54. exit 1
  55. }
  56. }
  57. # 收集系统指标
  58. SYSMONITOR_PID=""
  59. start_system_monitor() {
  60. local interval=5
  61. local output_file="$1"
  62. (
  63. echo "timestamp,cpu_percent,memory_mb,disk_read_mb,disk_write_mb" > "$output_file"
  64. while true; do
  65. local ts=$(date '+%Y-%m-%d %H:%M:%S')
  66. local cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' 2>/dev/null || echo "0")
  67. local mem=$(free -m | awk '/Mem:/{print $3}' 2>/dev/null || echo "0")
  68. local dr=$(cat /proc/diskstats 2>/dev/null | awk '{r+=$6} END{print r/2048}' || echo "0")
  69. local dw=$(cat /proc/diskstats 2>/dev/null | awk '{w+=$10} END{print w/2048}' || echo "0")
  70. echo "$ts,$cpu,$mem,$dr,$dw" >> "$output_file"
  71. sleep $interval
  72. done
  73. ) &
  74. SYSMONITOR_PID=$!
  75. }
  76. stop_system_monitor() {
  77. if [[ -n "$SYSMONITOR_PID" ]]; then
  78. kill "$SYSMONITOR_PID" 2>/dev/null || true
  79. wait "$SYSMONITOR_PID" 2>/dev/null || true
  80. SYSMONITOR_PID=""
  81. fi
  82. }
  83. # 收集系统信息
  84. collect_system_info() {
  85. local output_file="$1"
  86. cat > "$output_file" << EOF
  87. # 系统环境信息
  88. - 主机名: $(hostname)
  89. - 操作系统: $(uname -a)
  90. - CPU: $(nproc) 核
  91. - 内存: $(free -h | awk '/Mem:/{print $2}')
  92. - 磁盘: $(df -h / | awk 'NR==2{print $2 " total, " $4 " available"}')
  93. - Python: $(python3 --version 2>&1)
  94. - 测试时间: $(date '+%Y-%m-%d %H:%M:%S')
  95. - 快速模式: $QUICK_MODE
  96. EOF
  97. }
  98. # ==================== 测试配置 ====================
  99. if $QUICK_MODE; then
  100. REST_USERS=50
  101. REST_DURATION="30s"
  102. WS_CLIENTS=100
  103. WS_DURATION=30
  104. MQTT_DEVICES=100
  105. MQTT_DURATION=30
  106. DB_RECORDS=100000
  107. else
  108. REST_USERS=500
  109. REST_DURATION="3m"
  110. WS_CLIENTS=1000
  111. WS_DURATION=120
  112. MQTT_DEVICES=1000
  113. MQTT_DURATION=120
  114. DB_RECORDS=1000000
  115. fi
  116. # ==================== 开始测试 ====================
  117. echo ""
  118. echo "============================================================"
  119. echo "🏗️ 水务管理系统 - 性能压力测试"
  120. echo "============================================================"
  121. echo "测试时间: $(date '+%Y-%m-%d %H:%M:%S')"
  122. echo "输出目录: $OUTPUT_DIR"
  123. echo "快速模式: $QUICK_MODE"
  124. echo "============================================================"
  125. # 检查依赖
  126. check_python_deps
  127. # 收集系统信息
  128. SYSTEM_INFO="$OUTPUT_DIR/system_info.md"
  129. collect_system_info "$SYSTEM_INFO"
  130. # 启动系统监控
  131. SYSMON_CSV="$OUTPUT_DIR/system_metrics.csv"
  132. start_system_monitor "$SYSMON_CSV"
  133. # 注册退出清理
  134. trap stop_system_monitor EXIT
  135. # ---------- 1. REST API 压力测试 ----------
  136. log ""
  137. log "=========================================="
  138. log "📡 测试 1/4: REST API 压力测试"
  139. log "=========================================="
  140. REST_RESULT="$OUTPUT_DIR/rest_api_result.json"
  141. if command -v locust &>/dev/null; then
  142. timeout 600 locust -f locustfile.py \
  143. --host="http://${API_HOST}:${API_PORT}" \
  144. --headless -u "$REST_USERS" -r 10 \
  145. --run-time "$REST_DURATION" \
  146. --csv="$OUTPUT_DIR/rest_api" \
  147. --json 2>&1 | tee "$OUTPUT_DIR/rest_api.log" || true
  148. log "✅ REST API 测试完成"
  149. else
  150. log "⚠️ locust 未安装,跳过 REST API 测试"
  151. echo '{"skipped": true, "reason": "locust not installed"}' > "$REST_RESULT"
  152. fi
  153. # ---------- 2. WebSocket 压力测试 ----------
  154. log ""
  155. log "=========================================="
  156. log "🔌 测试 2/4: WebSocket 压力测试"
  157. log "=========================================="
  158. WS_RESULT="$OUTPUT_DIR/websocket_result.json"
  159. timeout 600 python3 websocket_stress.py \
  160. --host "$WS_HOST" --port "$WS_PORT" \
  161. --clients "$WS_CLIENTS" --duration "$WS_DURATION" \
  162. --output "$WS_RESULT" 2>&1 | tee "$OUTPUT_DIR/websocket.log" || true
  163. log "✅ WebSocket 测试完成"
  164. # ---------- 3. MQTT IoT 压力测试 ----------
  165. log ""
  166. log "=========================================="
  167. log "📡 测试 3/4: IoT MQTT 压力测试"
  168. log "=========================================="
  169. MQTT_RESULT="$OUTPUT_DIR/mqtt_result.json"
  170. timeout 600 python3 mqtt_iot_stress.py \
  171. --broker "$MQTT_BROKER" --port "$MQTT_PORT" \
  172. --devices "$MQTT_DEVICES" --duration "$MQTT_DURATION" \
  173. --output "$MQTT_RESULT" 2>&1 | tee "$OUTPUT_DIR/mqtt.log" || true
  174. log "✅ MQTT 测试完成"
  175. # ---------- 4. 数据库查询测试 ----------
  176. log ""
  177. log "=========================================="
  178. log "🗄️ 测试 4/4: 数据库查询压力测试"
  179. log "=========================================="
  180. DB_RESULT="$OUTPUT_DIR/db_query_result.json"
  181. timeout 600 python3 db_query_stress.py \
  182. --host "$DB_HOST" --port "$DB_PORT" \
  183. --db "$DB_NAME" --user "$DB_USER" --password "$DB_PASS" \
  184. --generate-data "$DB_RECORDS" \
  185. --index-compare \
  186. --output "$DB_RESULT" 2>&1 | tee "$OUTPUT_DIR/db_query.log" || true
  187. log "✅ 数据库测试完成"
  188. # ==================== 停止监控 ====================
  189. stop_system_monitor
  190. # ==================== 生成综合报告 ====================
  191. log ""
  192. log "=========================================="
  193. log "📝 生成综合报告"
  194. log "=========================================="
  195. REPORT_FILE="$OUTPUT_DIR/report.md"
  196. # 复制报告模板并填充
  197. if [[ -f report_template.md ]]; then
  198. cp report_template.md "$REPORT_FILE"
  199. # 追加实际结果
  200. cat >> "$REPORT_FILE" << EOF
  201. ---
  202. ## 实际测试结果
  203. ### 测试环境
  204. $(cat "$SYSTEM_INFO")
  205. ### REST API 结果
  206. \`\`\`
  207. $(tail -30 "$OUTPUT_DIR/rest_api.log" 2>/dev/null || echo "无数据")
  208. \`\`\`
  209. ### WebSocket 结果
  210. \`\`\`json
  211. $(cat "$WS_RESULT" 2>/dev/null || echo "无数据")
  212. \`\`\`
  213. ### MQTT IoT 结果
  214. \`\`\`json
  215. $(cat "$MQTT_RESULT" 2>/dev/null || echo "无数据")
  216. \`\`\`
  217. ### 数据库查询结果
  218. \`\`\`json
  219. $(cat "$DB_RESULT" 2>/dev/null || echo "无数据")
  220. \`\`\`
  221. ### 系统资源指标
  222. \`\`\`csv
  223. $(head -20 "$SYSMON_CSV" 2>/dev/null || echo "无数据")
  224. \`\`\`
  225. EOF
  226. else
  227. # 简单报告
  228. cat > "$REPORT_FILE" << EOF
  229. # 性能压力测试报告
  230. ## 测试时间
  231. $(date '+%Y-%m-%d %H:%M:%S')
  232. ## 测试环境
  233. $(cat "$SYSTEM_INFO")
  234. ## 测试结果摘要
  235. | 测试项 | 状态 | 结果文件 |
  236. |--------|------|----------|
  237. | REST API | ✅ | rest_api_result.json |
  238. | WebSocket | ✅ | websocket_result.json |
  239. | MQTT IoT | ✅ | mqtt_result.json |
  240. | 数据库查询 | ✅ | db_query_result.json |
  241. ## 系统资源指标
  242. 见 system_metrics.csv
  243. EOF
  244. fi
  245. log "✅ 综合报告已生成: $REPORT_FILE"
  246. # ==================== 完成 ====================
  247. echo ""
  248. echo "============================================================"
  249. echo "🎉 所有压力测试完成!"
  250. echo "============================================================"
  251. echo "输出目录: $OUTPUT_DIR"
  252. echo "文件列表:"
  253. ls -la "$OUTPUT_DIR/"
  254. echo "============================================================"