- 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>
95 行
3.1 KiB
Bash
可执行文件
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"
|