Files
SQS/load_test.sh
T

205 lines
8.5 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# load_test.sh — Нагрузочный тест SQS-сервиса
# Замеряет: latency, throughput, параллельную работу
# Требования: curl, bash
# Запуск: bash load_test.sh
set -euo pipefail
# ═══════════════════════════════════════════
# КОНФИГУРАЦИЯ — измените под свой тенант
# ═══════════════════════════════════════════
SQS_ENDPOINT="https://sqs.kube5s.ru/sqs/test001"
AUTH="SQSAK-test001-ae4dc8:J8mElXq8Nwww8iFRtGJCm8KfxM9XSTluTqS2A67xsEE"
VER="2012-11-05"
TS=$(date +%s)
TMPDIR=$(mktemp -d /tmp/sqs-load-XXXXX)
MESSAGES=50 # Сообщений в последовательном тесте
WORKERS=5 # Параллельных воркеров
MSGS_PER_WORKER=20 # Сообщений на воркер
STRESS_SEC=30 # Секунд стресс-теста
ms_now() { date +%s%N | cut -b1-13; }
call() {
curl -s --max-time 30 -u "$AUTH" "${SQS_ENDPOINT}?${1}&Version=${VER}" 2>&1
}
echo "╔═══════════════════════════════════════════════════════╗"
echo "║ SQS Load Test — $(date '+%Y-%m-%d %H:%M:%S') ║"
echo "║ Endpoint: ${SQS_ENDPOINT} ║"
echo "║ Параметры: ${MESSAGES} seq, ${WORKERS}×${MSGS_PER_WORKER} par, ${STRESS_SEC}s stress ║"
echo "╚═══════════════════════════════════════════════════════╝"
echo ""
# ═══════════════════════════════════════════
echo "── 1. Latency (20 замеров) ──"
# ═══════════════════════════════════════════
QL="lq-lat-${TS}"
call "Action=CreateQueue&QueueName=${QL}" >/dev/null
TIMES=()
for i in $(seq 1 20); do
T1=$(ms_now)
call "Action=SendMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QL}&MessageBody=lat-${i}" >/dev/null
T2=$(ms_now)
TIMES+=( $((T2 - T1)) )
done
SUM=0; MIN=999999; MAX=0
for t in "${TIMES[@]}"; do
SUM=$((SUM + t))
[ "$t" -lt "$MIN" ] && MIN=$t
[ "$t" -gt "$MAX" ] && MAX=$t
done
AVG=$((SUM / ${#TIMES[@]}))
echo " SendMessage: avg=${AVG}ms min=${MIN}ms max=${MAX}ms"
TIMES=()
for i in $(seq 1 20); do
T1=$(ms_now)
call "Action=ReceiveMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QL}&MaxNumberOfMessages=1" >/dev/null
T2=$(ms_now)
TIMES+=( $((T2 - T1)) )
done
SUM=0; MIN=999999; MAX=0
for t in "${TIMES[@]}"; do
SUM=$((SUM + t))
[ "$t" -lt "$MIN" ] && MIN=$t
[ "$t" -gt "$MAX" ] && MAX=$t
done
AVG=$((SUM / ${#TIMES[@]}))
echo " ReceiveMessage: avg=${AVG}ms min=${MIN}ms max=${MAX}ms"
call "Action=DeleteQueue&QueueUrl=${SQS_ENDPOINT}/test001/${QL}" >/dev/null
echo ""
# ═══════════════════════════════════════════
echo "── 2. Последовательный throughput (${MESSAGES} сообщений) ──"
# ═══════════════════════════════════════════
QS="lq-seq-${TS}"
call "Action=CreateQueue&QueueName=${QS}" >/dev/null
T1=$(ms_now)
OK=0; ERR=0
for i in $(seq 1 $MESSAGES); do
R=$(call "Action=SendMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QS}&MessageBody=seq-${i}")
if echo "$R" | grep -q "MessageId"; then OK=$((OK + 1)); else ERR=$((ERR + 1)); fi
done
T2=$(ms_now)
ELAPSED=$((T2 - T1))
RPS=$(( OK * 1000 / (ELAPSED + 1) ))
echo " Send: ${OK} OK / ${ERR} ERR за $((ELAPSED/1000)).$((ELAPSED%1000))s (${RPS} msg/s)"
T1=$(ms_now)
GOT=0; EMPTY=0
for _ in $(seq 1 $((MESSAGES + 30))); do
R=$(call "Action=ReceiveMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QS}&MaxNumberOfMessages=10")
C=$(echo "$R" | grep -c "<Message>" || true)
if [ "$C" -gt 0 ]; then GOT=$((GOT + C)); else EMPTY=$((EMPTY + 1)); [ "$EMPTY" -ge 3 ] && break; fi
[ "$GOT" -ge "$MESSAGES" ] && break
done
T2=$(ms_now)
ELAPSED=$((T2 - T1))
RPS=$(( GOT * 1000 / (ELAPSED + 1) ))
echo " Recv: ${GOT}/${MESSAGES} за $((ELAPSED/1000)).$((ELAPSED%1000))s (${RPS} msg/s)"
call "Action=DeleteQueue&QueueUrl=${SQS_ENDPOINT}/test001/${QS}" >/dev/null
echo ""
# ═══════════════════════════════════════════
echo "── 3. Параллельная отправка (${WORKERS} × ${MSGS_PER_WORKER}) ──"
# ═══════════════════════════════════════════
QP="lq-par-${TS}"
call "Action=CreateQueue&QueueName=${QP}" >/dev/null
worker_send() {
local wid=$1; local ok=0
for i in $(seq 1 $MSGS_PER_WORKER); do
R=$(curl -s --max-time 30 -u "$AUTH" "${SQS_ENDPOINT}?Action=SendMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QP}&MessageBody=w${wid}-${i}&Version=${VER}" 2>&1)
echo "$R" | grep -q "MessageId" && ok=$((ok + 1))
done
echo "$ok" > "${TMPDIR}/w-${wid}.ok"
}
T1=$(ms_now)
for w in $(seq 1 $WORKERS); do worker_send $w & done
wait
T2=$(ms_now)
ELAPSED=$((T2 - T1))
TOT_OK=0
for w in $(seq 1 $WORKERS); do
[ -f "${TMPDIR}/w-${w}.ok" ] && TOT_OK=$((TOT_OK + $(cat "${TMPDIR}/w-${w}.ok")))
done
TOT=$((WORKERS * MSGS_PER_WORKER))
RPS=$(( TOT_OK * 1000 / (ELAPSED + 1) ))
echo " Send: ${TOT_OK}/${TOT} за $((ELAPSED/1000)).$((ELAPSED%1000))s (${RPS} msg/s)"
# Параллельный receive
worker_recv() {
local wid=$1; local ok=0; local empty=0
for _ in $(seq 1 $((MSGS_PER_WORKER + 10))); do
R=$(curl -s --max-time 30 -u "$AUTH" "${SQS_ENDPOINT}?Action=ReceiveMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QP}&MaxNumberOfMessages=10&Version=${VER}" 2>&1)
C=$(echo "$R" | grep -c "<Message>" || true)
if [ "$C" -gt 0 ]; then ok=$((ok + C)); else empty=$((empty + 1)); [ "$empty" -ge 3 ] && break; fi
done
echo "$ok" > "${TMPDIR}/r-${wid}.ok"
}
T1=$(ms_now)
for w in $(seq 1 $WORKERS); do worker_recv $w & done
wait
T2=$(ms_now)
ELAPSED=$((T2 - T1))
TOT_RECV=0
for w in $(seq 1 $WORKERS); do
[ -f "${TMPDIR}/r-${w}.ok" ] && TOT_RECV=$((TOT_RECV + $(cat "${TMPDIR}/r-${w}.ok")))
done
RPS=$(( TOT_RECV * 1000 / (ELAPSED + 1) ))
echo " Recv: ${TOT_RECV}/${TOT} за $((ELAPSED/1000)).$((ELAPSED%1000))s (${RPS} msg/s)"
call "Action=DeleteQueue&QueueUrl=${SQS_ENDPOINT}/test001/${QP}" >/dev/null
echo ""
# ═══════════════════════════════════════════
echo "── 4. Стресс-петля (${STRESS_SEC}s) ──"
# ═══════════════════════════════════════════
QX="lq-stress-${TS}"
call "Action=CreateQueue&QueueName=${QX}" >/dev/null
SENT=0; RECV=0; ERRS=0
T_END=$(($(date +%s) + STRESS_SEC))
while [ "$(date +%s)" -lt "$T_END" ]; do
R=$(call "Action=SendMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QX}&MessageBody=s-${SENT}")
if echo "$R" | grep -q "MessageId"; then SENT=$((SENT + 1)); else ERRS=$((ERRS + 1)); fi
R=$(call "Action=ReceiveMessage&QueueUrl=${SQS_ENDPOINT}/test001/${QX}&MaxNumberOfMessages=10")
C=$(echo "$R" | grep -c "<Message>" || true)
RECV=$((RECV + C))
done
echo " Длительность: ${STRESS_SEC}s"
echo " Отправлено: ${SENT} ($(( SENT / (STRESS_SEC + 1) )) msg/s)"
echo " Получено: ${RECV} ($(( RECV / (STRESS_SEC + 1) )) msg/s)"
echo " Ошибки: ${ERRS}"
call "Action=DeleteQueue&QueueUrl=${SQS_ENDPOINT}/test001/${QX}" >/dev/null
echo ""
# ═══════════════════════════════════════════
echo "╔═══════════════════════════════════════════════════════╗"
echo "║ НАГРУЗОЧНЫЙ ТЕСТ ЗАВЕРШЁН ║"
echo "║ $(date '+%Y-%m-%d %H:%M:%S') ║"
echo "╚═══════════════════════════════════════════════════════╝"
rm -rf "$TMPDIR"