79 lines
2.9 KiB
Python
79 lines
2.9 KiB
Python
"""HTTP-стресс против contracts-flask (standalone, не pytest).
|
|
|
|
Создаёт параллельную нагрузку на /upload большими файлами + /health,
|
|
замеряет RPS, ошибки, таймауты. Цель — «разогреть» сервис и выявить
|
|
деградацию/обрывы (шлюз, OOM, SQLite).
|
|
|
|
Запуск:
|
|
python tests/load/stress_http.py --url http://127.0.0.1:5000 \
|
|
--n 1000 --threads 32 --size 100000
|
|
|
|
Пример против прода (осторожно):
|
|
python tests/load/stress_http.py --url https://contractor.pythonk8s.dev.nubes.ru \
|
|
--n 200 --threads 16 --size 500000
|
|
"""
|
|
import argparse
|
|
import time
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
import httpx
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser(description="HTTP-стресс contracts-flask")
|
|
ap.add_argument("--url", default="http://127.0.0.1:5000")
|
|
ap.add_argument("--n", type=int, default=1000, help="число запросов")
|
|
ap.add_argument("--threads", type=int, default=32, help="параллельных потоков")
|
|
ap.add_argument("--size", type=int, default=100000, help="размер файла в байтах (если не задан --file)")
|
|
ap.add_argument("--file", default=None, help="путь к реальному файлу (заменяет сгенерированный)")
|
|
ap.add_argument("--health-only", action="store_true", help="только /health, без загрузки файлов")
|
|
args = ap.parse_args()
|
|
|
|
if args.file:
|
|
import os as _os
|
|
fname = _os.path.basename(args.file)
|
|
with open(args.file, "rb") as _f:
|
|
payload = _f.read()
|
|
real_size = len(payload)
|
|
else:
|
|
fname = "load.docx"
|
|
payload = b"x" * args.size
|
|
real_size = args.size
|
|
ok = 0
|
|
err = 0
|
|
slow = 0
|
|
t0 = time.time()
|
|
|
|
def one(_):
|
|
nonlocal ok, err, slow
|
|
try:
|
|
with httpx.Client(timeout=30) as c:
|
|
if args.health_only:
|
|
r = c.get(f"{args.url}/health")
|
|
else:
|
|
r = c.post(
|
|
f"{args.url}/upload",
|
|
files={"files": (fname, payload, "application/octet-stream")},
|
|
)
|
|
if r.status_code == 200:
|
|
ok += 1
|
|
else:
|
|
err += 1
|
|
except httpx.TimeoutException:
|
|
err += 1
|
|
slow += 1
|
|
except Exception:
|
|
err += 1
|
|
|
|
with ThreadPoolExecutor(max_workers=args.threads) as ex:
|
|
list(ex.map(one, range(args.n)))
|
|
|
|
elapsed = time.time() - t0
|
|
print(f"url={args.url}")
|
|
print(f"n={args.n} threads={args.threads} size={real_size}B file={args.file or '(gen)'} health_only={args.health_only}")
|
|
print(f"ok={ok} err={err} timeouts={slow} elapsed={elapsed:.1f}s rps={args.n / elapsed:.1f}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|