XuqmGroup-PrivateDeploy/scripts/bench.sh
徐勤民 9eabe0d699 feat: implement complete private deployment scripts (P1-P4)
- upgrade.sh/rollback.sh: backup→pull→rolling restart→healthcheck→auto-rollback
- backup.sh/restore.sh: mysqldump+redis BGSAVE+config tar, SHA256 manifest, restore with checksum verification
- healthcheck.sh: Docker/container/MySQL/Redis/HTTP/disk checks, JSON output to .deploy-state/
- doctor.sh: sanitized diagnostics archive, vendor API TCP connectivity, cert expiry
- export-offline-bundle.sh: docker pull+save for all profile images, load-images.sh, SHA256
- configure.sh: interactive/non-interactive mode, MySQL/Redis mode selection, domain prompts
- enable-service.sh: domain validation, docker pull + compose up, healthcheck
- disable-service.sh: compose stop+rm, profile removal, render-config
- renew-cert.sh: acme.sh/certbot, --dry-run, backup old cert, nginx reload on success
- alert-webhook.sh: WeCom/DingTalk/Feishu webhook, message sanitization
- bench.sh: ab/wrk/curl benchmark, JSON report with docker stats
- rotate-secrets.sh: JWT and internal token rotation
- vendor credential templates: push.env and store-submit.env with full credential comments
- render-config.sh: auto-sync SDK URL env vars (SDK_FILE_SERVICE_URL, SDK_IM_API_URL, SDK_IM_WS_URL)
- All scripts pass bash -n syntax check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 20:49:25 +08:00

95 行
3.1 KiB
Bash
可执行文件

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
. "$ROOT_DIR/scripts/lib.sh"
load_env
PROFILE="${1:-base}"
DURATION="${2:-30}"
REPORT_FILE="$ROOT_DIR/dist/bench-$(date +%Y%m%d%H%M%S).json"
mkdir -p "$ROOT_DIR/dist"
audit "bench" "STARTED" "profile=$PROFILE duration=${DURATION}s"
progress "bench" "STARTED" "profile=$PROFILE"
require_cmd curl
require_cmd docker
BASE_URL="${CONSOLE_DOMAIN:-http://localhost}"
bench_http() {
local name="$1"
local url="$2"
local concurrency="${3:-10}"
local requests="${4:-100}"
local pass_rps="${5:-50}"
local pass_p99_ms="${6:-500}"
printf 'Benchmarking %s (%s)...\n' "$name" "$url"
if command -v ab >/dev/null 2>&1; then
RAW="$(ab -n "$requests" -c "$concurrency" -q "$url" 2>/dev/null || true)"
RPS="$(printf '%s' "$RAW" | grep 'Requests per second' | awk '{print $4}' | cut -d. -f1)"
P99="$(printf '%s' "$RAW" | grep '99%' | awk '{print $2}')"
RPS="${RPS:-0}"
P99="${P99:-9999}"
elif command -v wrk >/dev/null 2>&1; then
RAW="$(wrk -t2 -c"$concurrency" -d"${DURATION}s" "$url" 2>/dev/null || true)"
RPS="$(printf '%s' "$RAW" | grep 'Requests/sec' | awk '{print $2}' | cut -d. -f1)"
P99="${P99:-0}"
RPS="${RPS:-0}"
else
# Fallback: sequential curl timing
total_ms=0
for _ in $(seq 1 20); do
ms="$(curl -sk -o /dev/null -w '%{time_total}' --max-time 5 "$url" 2>/dev/null | awk '{printf "%d", $1*1000}')"
total_ms=$((total_ms + ms))
done
AVG_MS=$((total_ms / 20))
RPS=$((1000 / (AVG_MS + 1)))
P99="$AVG_MS"
fi
PASS="true"
[ "$RPS" -lt "$pass_rps" ] && PASS="false"
[ "$P99" -gt "$pass_p99_ms" ] && PASS="false"
printf ' RPS: %s (min %s) | P99: %sms (max %sms) | %s\n' \
"$RPS" "$pass_rps" "$P99" "$pass_p99_ms" "$( [ "$PASS" = "true" ] && printf 'PASS' || printf 'FAIL')"
printf '{"name":"%s","url":"%s","rps":%s,"p99_ms":%s,"target_rps":%s,"target_p99_ms":%s,"pass":%s}' \
"$name" "$url" "$RPS" "$P99" "$pass_rps" "$pass_p99_ms" "$PASS"
}
RESULTS=()
RESULTS+=("$(bench_http "tenant-api-health" "$BASE_URL/actuator/health" 5 50 20 1000)")
if printf '%s' "$PROFILE" | grep -q 'im' && [ -n "${IM_DOMAIN:-}" ]; then
RESULTS+=("$(bench_http "im-api-health" "${IM_DOMAIN}/actuator/health" 5 50 20 1000)")
fi
if printf '%s' "$PROFILE" | grep -q 'update' && [ -n "${UPDATE_DOMAIN:-}" ]; then
RESULTS+=("$(bench_http "update-api-health" "${UPDATE_DOMAIN}/actuator/health" 5 50 20 1000)")
fi
# Docker stats snapshot
DOCKER_STATS="$(docker stats --no-stream --format '{"container":"{{.Name}}","cpu":"{{.CPUPerc}}","mem":"{{.MemUsage}}"}' 2>/dev/null || echo '[]')"
RESULTS_JSON="$(printf '%s\n' "${RESULTS[@]}" | paste -sd ',' - | sed 's/^/[/' | sed 's/$/]/')"
cat > "$REPORT_FILE" <<EOF
{
"timestamp": "$(now)",
"profile": "$PROFILE",
"durationSec": $DURATION,
"privateVersion": "${PRIVATE_VERSION:-unknown}",
"results": $RESULTS_JSON,
"dockerStats": $DOCKER_STATS
}
EOF
audit "bench" "DONE" "report=$REPORT_FILE"
progress "bench" "DONE" "profile=$PROFILE"
printf 'Benchmark report: %s\n' "$REPORT_FILE"