可靠度
概觀
四項可靠度控制讓 LoadDensity 能在 CI 無人值守跑而不變成「flake 工廠」:
自適應重試 — 指數退避 + 抖動 + per-error-class 預算;短暫抖動會 自動回復,真正的 bug 立刻暴露。
失敗預算 / Circuit breaker — 滑動視窗錯誤率;一旦回歸開始連鎖, 整次測試會自我中止。
網路條件器 — per task 注入延遲 / 抖動 / 丟包,無需 kernel
tc或外部 proxy。Process supervisor — 殺死殭屍的 Locust / gevent worker,並對任意 callable 套上硬牆鐘超時。
四者彼此獨立,任意搭配即可;皆位於
je_load_density.utils.reliability。
自適應重試
classify_error 將例外歸成三類:
transient— 連線失敗、timeout、remote disconnect(預設預算 5)flaky—AssertionError、``JSONDecodeError``(預設預算 2)permanent— 其餘(預算 0,立即丟出)
from je_load_density import AdaptiveRetryPolicy, run_with_retry
policy = AdaptiveRetryPolicy(
transient_budget=5, flaky_budget=2,
base_delay=0.1, max_delay=2.0,
backoff_factor=2.0, jitter=0.25,
)
run_with_retry(lambda: do_request(), policy=policy)
action JSON 內 per-task 宣告:
{"method": "post", "request_url": "${var.base}/x",
"retry": {"transient": 3, "flaky": 1, "base_delay": 0.2}}
失敗預算
from je_load_density import install_failure_budget
budget = install_failure_budget(
threshold=0.05, # 錯誤率 > 5%
window_seconds=30, # ...近 30 秒內
min_samples=50, # ...且至少 50 筆請求
runner_quit_callback=lambda: env.runner.quit(),
)
被觸發後僅呼叫一次 runner_quit_callback,之後的失敗會被忽略。
網路條件器
per task 注入延遲 / 抖動 / 丟包;丟包以拋出 ConnectionError
模擬(因此會被 retry 視為 transient)。
from je_load_density import install_network_conditioner
install_network_conditioner(
latency_ms=50, jitter_ms=20, loss_rate=0.01,
name_filter="/checkout", # 僅此 endpoint
)
Process supervisor
from je_load_density import ProcessSupervisor, with_watchdog
killed = ProcessSupervisor().kill_orphans() # 需 psutil 軟相依
result = with_watchdog(
lambda: execute_action(action_json),
timeout_seconds=600,
on_timeout=lambda: print("dumping state…"),
)
Action JSON 指令
指令 |
說明 |
|---|---|
|
訂閱 Locust request 事件,加入滑動視窗失敗預算 |
|
卸除 listener |
|
設定全域延遲 / 抖動 / 丟包注入 |
|
卸除注入 |