"""压并发:12 条同时投给调度层,看三件事。 1. 派发会不会打偏——调度层是「读 health 挑最闲的」,同时提交时几个请求可能读到同一份快照。 顺序提交测不出这个,必须真并发。 2. queue_position 和 eta_seconds 在排队时说了什么。 3. 队列有没有上限、超了会怎样。 """ import json, time, urllib.request from collections import Counter from concurrent.futures import ThreadPoolExecutor GW = "http://127.0.0.1:8000" N = 12 SPEC = {"prompt": "一只橘猫趴在洒满阳光的窗台上,慢慢眨眼", "frames": 22, "steps": 4, "turbo": True} def call(path, data=None, timeout=60): req = urllib.request.Request(GW + path, data=data, headers={"Content-Type": "application/json"} if data else {}) with urllib.request.urlopen(req, timeout=timeout) as r: return json.load(r) def submit(i): t = time.time() job = call("/v1/videos", json.dumps(dict(SPEC, seed=100 + i)).encode()) return i, job, time.time() - t t0 = time.time() with ThreadPoolExecutor(max_workers=N) as pool: results = sorted(pool.map(submit, range(N))) print(f"12 条并发提交耗时 {time.time() - t0:.2f}s\n") for i, job, dt in results: print(f" #{i:<2} {job['backend'][-4:]} queue_position={job['queue_position']} " f"eta={job['eta_seconds']}s ({dt:.2f}s)") spread = Counter(job["backend"][-4:] for _, job, _ in results) print(f"\n派发分布: {dict(sorted(spread.items()))} 理想是每个 {N // 4} 条") ids = [job["id"] for _, job, _ in results] print("\n--- 轮询") while True: time.sleep(30) states = [call(f"/v1/videos/{jid}") for jid in ids] c = Counter(s["status"] for s in states) print(f" {dict(c)}", flush=True) if all(s["status"] in ("done", "failed") for s in states): break total = time.time() - t0 print(f"\n12 条全部完成,墙钟 {total:.0f}s") for s in sorted(states, key=lambda s: s["created_at"]): took = s["finished_at"] - s["started_at"] wait = s["started_at"] - s["created_at"] print(f" {s['id'][:6]} {s['status']} 排队{wait:5.0f}s 执行{took:4.0f}s {s['backend'][-4:]}")