Skip to content

Repository files navigation

Version Python 3.8+ Zero Dependencies Tests MIT License Offline First

⚖️ ScaleForge

本地优先的系统设计容量模拟器 · 離線系統設計容量模擬器 · Local-first System Design Capacity Simulator
排队论解析模型 × 离散事件仿真双引擎,在写第一行部署代码前,先把系统「压到崩」看清楚瓶颈在哪。

简体中文 · 繁體中文 · English


简体中文

🔁 双引擎交叉验证:Erlang-C / M/M/c/K 闭式解析(毫秒级出结果)+ 纯标准库离散事件仿真(验证解析结论),全程离线、零第三方依赖。

🎉 项目介绍

ScaleForge(容量锻造台) 是一款面向后端工程师、SRE 与准备系统设计面试的开发者的离线容量规划与瓶颈推演工具。你用一份 JSON 描述系统拓扑(网关、服务、缓存、数据库、消息队列、Worker),它就能回答四个灵魂问题:

  1. 当前流量下,端到端 p50/p95/p99 延迟是多少?错误率多少?
  2. 第一个被压垮的组件是谁?调用链上的瓶颈路径是什么?
  3. 流量继续上涨,系统在哪个 RPS 断裂?离 SLO 击穿还有多少余量?
  4. 要扛住目标流量,每个组件至少需要扩到几个实例?一个月大概花多少钱?

😮‍💨 解决什么痛点

  • 系统设计材料大多是静态架构图和「加缓存、上队列」的经验口诀,缺少对排队行为的量化直觉:为什么利用率一过 70%,p99 就开始非线性飙升?
  • 真实压测要先把系统写出来、部署起来,成本高、周期长,还可能打挂共享环境;
  • 纸上算容量只会用「QPS ÷ 单机 QPS」,忽略排队等待、扇出调用、缓存穿透、超时重试放大,结果上线即雪崩。

🌟 自研差异化亮点

  • 🧮 双引擎互验:闭式排队模型(Erlang-C、有限队列 M/M/c/K、Allen-Cunneen 通用近似、Little 定律、尾延迟反解)与独立实现的离散事件仿真互为校验,数字不是「画出来好看」的。
  • 🧾 Scenario-as-Code:一份 JSON 即可版本化、进 Git、进 CI;支持 --strict 在 SLO 击穿时以非零退出码拦截变更。
  • 🧗 负载扫描与断裂点检测:自动扫描 RPS 区间,分别给出利用率上限、p99 SLO 上限、错误率上限,取最严约束作为安全水位。
  • 🩺 瓶颈根因链 + 扩容反解:定位入口到瓶颈的调用路径,并反解每个组件满足目标利用率所需的最少并发数/副本数。
  • 🌩️ 故障机制建模:有限队列丢弃、超时 + 有限次重试的负载放大效应(被放弃的请求仍在下游占用算力——这正是重试风暴的机理)、缓存命中率吸收、同步/异步扇出。
  • 📉 四种报告形态:彩色终端报告 + ASCII 趋势图、机器可读 JSON、Markdown、单文件离线 HTML 报告(手写 SVG 图表,无任何外部资产)
  • 📦 零依赖、跨平台、单文件:Python 3.8+ 标准库即可运行;一条命令打成 scaleforge.pyz 单文件随身带。

💡 灵感来源

项目受近期 GitHub 热门的分布式系统教学模拟器启发(画布式拖拽、拉高流量观察排队行为)。我们认同「用实验代替口诀」的理念,但选择了一条不同的路:CLI / 代码优先、可复现、可进 CI、解析与仿真互验、直接产出容量规划结论,并补充了画布产品不具备的 SLO 水位计算、扩容反解与成本估算。未使用其任何代码或素材,全部实现为独立自研。

✨ 核心特性

模块 能力
🧮 解析引擎 M/M/1、M/M/c(Erlang-C 等待概率)、M/M/c/K 有限队列丢弃率、Allen-Cunneen 非指数服务近似、p50/p95/p99 尾延迟闭式反解
🎲 离散事件仿真 自写事件循环:泊松到达、指数/定长/Gamma 服务时间、多服务台、有界 FIFO 队列、超时计时器、有限重试、同步/并行扇出、缓存吸收,固定随机种子可复现
🕸️ 拓扑流量传播 DAG 调用图、按边扇出倍数、缓存穿透率、重试放大定点迭代收敛、并行取 max / 串行求和的延迟合成
  • 📈 负载扫描(Sweep):线性抬升 RPS,输出 p99 / 利用率 / 错误率 / 有效吞吐曲线,自动标注安全水位与余量百分比。
  • 🩺 诊断与建议:过载、高利用率、队列溢出、超时风险、重试放大、缓存机会等分级发现项(critical / warning / ok),每条都附带可执行建议。
  • 💰 成本估算:内置通用实例目录(参考价,可覆盖),估算月度成本与每百万请求成本。
  • 🖥️ 终端体验:ANSI 彩色表格、ASCII 折线图与迷你趋势线,--no-color 适配管道与 CI。
  • 🧰 库友好:每个引擎都是纯函数式 API,可直接嵌入你自己的自动化容量评审流水线。
  • 🔒 隐私安全:不发起任何网络请求、不收集遥测,场景数据永不出本机;无正则注入、无动态执行,JSON 仅做结构解析。

🚀 快速开始

环境要求

  • Python 3.8 及以上(Windows / macOS / Linux 均可),无需安装任何第三方依赖

方式一:源码直接运行(推荐先试)

git clone https://github.com/gitstq/ScaleForge.git
cd ScaleForge

# 跑一遍内置示例:解析 + 仿真交叉验证 + 负载扫描
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep --no-color

方式二:生成自己的场景模板

python3 -m scaleforge init my-system.json   # 写入一份带注释结构的示例
python3 -m scaleforge check my-system.json  # 先校验拓扑与字段
python3 -m scaleforge analyze my-system.json

方式三:单文件 zipapp(拷走即用)

bash scripts/build_pyz.sh                 # Windows 用 scripts/build_pyz.ps1
python3 dist/scaleforge.pyz --version
python3 dist/scaleforge.pyz analyze examples/01_monolith.json

方式四:pip 安装为命令

pip install .
scaleforge analyze examples/03_retry_storm.json --rps 60

最快的一次完整体验:

# 把一个「超时 90ms + 重试 2 次」的系统从 60 rps 加压到 140 rps,看重试风暴
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 60 --no-color
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 140 --sweep --no-color

📖 详细使用指南

场景文件结构(Scenario Schema)

{
  "name": "my-service",
  "description": "一句话描述",
  "entrypoint": "gateway",
  "rps": 120.0,
  "slo": { "p99_ms": 400.0, "max_error_rate": 0.001, "max_utilization": 0.7 },
  "components": [
    { "name": "gateway", "kind": "gateway", "replicas": 2, "concurrency": 8,
      "service_time_ms": 3.0, "instance_type": "standard" }
  ],
  "edges": [
    { "source": "gateway", "target": "orders", "calls": 1, "mode": "parallel" }
  ]
}

组件字段说明:

字段 类型 默认 说明
name string 必填 组件唯一名
kind string service gateway/service/cache/database/queue/worker/external
replicas int 1 副本数
concurrency int 1 单副本并发服务台数;总服务台 = 副本 × 并发
service_time_ms float 0 单次调用平均处理耗时;0 表示纯透传节点(如逻辑队列)
service_cv float 1.0 服务时间变异系数:0=定长,1=指数分布,其余按 Gamma
max_queue int -1 等待队列长度,-1 无界;满了即丢弃
cache_hit float 0.0 本节点就地吸收、不再调用下游的比例(如缓存命中率)
timeout_ms float 0 调用方对该组件的超时;>0 时启用超时概率计算
retries int 0 超时/丢弃后的重试次数(重试策略声明在被调方)
instance_type string 自动 成本目录中的实例型号

边字段: calls(每个父请求产生的调用次数,支持小数表示概率调用)、modesequential 串行延迟求和 / parallel 并行取最大)。

命令一览

命令 作用 常用参数
init [path] 生成示例场景 --force 覆盖
check <file> 仅校验场景
analyze <file> 稳态解析 + 诊断 + 成本 --rps 覆盖流量;--sim 加仿真;--sweep 加扫描;--strict CI 门禁;--format text/json/md/html--out 写文件
simulate <file> 只跑离散事件仿真 --duration 60 --warmup 5 --seed 42
sweep <file> 只做负载扫描 --min-rps --max-rps --steps

典型使用场景

场景 A:容量评审(给目标流量,反推资源)

python3 -m scaleforge analyze design.json --rps 500 --format md --out review.md

报告的 Capacity plan 直接给出每个组件「当前服务台 → 所需服务台 → 副本数建议 → 剩余承载余量」。

场景 B:CI 容量门禁(架构改动导致 SLO 击穿即失败)

python3 -m scaleforge analyze design.json --rps 300 --strict
# SLO 满足退出码 0;击穿退出码 3,可直接挂在流水线里

场景 C:离线 HTML 报告(发给评审会)

python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep \
  --format html --out report.html

样例报告见 docs/sample-report.html(浏览器直接打开,无需联网),拓扑示意见 docs/topology.svg

场景 D:当 Python 库嵌入

from scaleforge.model import Scenario
from scaleforge.engine import analyze
from scaleforge.sweep import sweep
from scaleforge.diagnose import diagnose

scn = Scenario.load("design.json")
result = analyze(scn, rps=300)
print(result.e2e_p99_ms, result.goodput_rps, result.bottleneck)

plan = diagnose(scn, result)
for item in plan.capacity_plan:
    print(item.component, item.required_servers, item.recommended_replicas)

curve = sweep(scn, 50, 800, steps=30)
print("安全水位 RPS:", curve.safe_rps)

输出解读

  • util(利用率):到达率 ÷ 总服务率。长期 ≥100% 队列无界增长;超过 SLO 设定的 max_utilization(默认 70%)即给出排队预警。
  • p99:端到端第 99 百分位延迟,沿关键路径合成(解析值,仿真报告给出独立测量值对照)。
  • drop:有界队列溢出比例;retry:重试造成的下游负载倍数。
  • safe load:扫描中同时满足利用率、p99、错误率三条 SLO 的最大 RPS。

演示

Offered load : 140.00 rps   Goodput: 0.00 rps   Errors: 100.0%   [SLO BREACHED]
component         kind         in rps  srv    util   wait ms    p99 ms    drop  retry
db                database     420.00    8  100.0%         ∞         ∞   65.4%  3.00x
✗ CRIT  [db] Arrival 420.0 rps >= service capacity 145.5 rps (rho -> 100%)
⚠ WARN  [db] Retries multiply downstream load by x3.00.

同一个系统在 60 rps 时 SLO 全绿,140 rps 时因「慢库 + 90ms 超时 + 2 次重试」把下游放大 3 倍后整体崩塌——这就是重试风暴,ScaleForge 在部署前就能把它算出来。 (运行录屏/GIF 占位:docs/demo.gif

❓ 常见问题

  • 解析引擎和仿真结果应该完全一致吗? 均值在低/中负载下应高度一致;尾延迟受仿真时长与随机种子影响会有统计波动,可加大 --duration 收敛。解析模型用于快速扫描,仿真用于最终验证。
  • 支持网络调用真实压测吗? 不支持,也刻意不做——ScaleForge 是离线建模工具,不发任何网络包;真实压测请配合 k6 / wrk / Locust。
  • 服务时间怎么测? 用线上 P50 均值作为 service_time_ms,用 P50/P99 估算变异系数 service_cv;不确定时保持默认 1.0(指数分布是保守上界)。

💡 设计思路与迭代规划

为什么是「双引擎」

闭式公式(Erlang-C 家族)毫秒级、可对整个流量区间做扫描,但依赖分布假设;离散事件仿真不依赖闭式假设、能刻画超时/重试这类动态过程,但每次运行有统计成本。ScaleForge 让两者共存:用解析引擎做扫描与规划,用仿真引擎做交叉验证,并且两套实现完全独立,避免同一个错误互相背书。

技术选型理由

  • 纯标准库 Python:容量计算是轻量数学问题,零依赖意味着任何机器、任何 CI、任何离线环境都能直接跑;heapq 足以承载事件驱动仿真。
  • JSON 而非自定义 DSL:零学习成本、天然可 diff、可被任何语言生成。
  • 手写 SVG 报告:HTML 报告不依赖 CDN/图表库,离线可开、可邮件转发、永不因为外链失效而白屏。

迭代路线图

  • v1.1:熔断器(open / half-closed / closed)状态机进入仿真引擎
  • v1.2:漏桶/令牌桶限流与自适应扩缩容(HPA 风格)策略仿真
  • v1.3:场景对比 diff(改副本数前后两份报告自动对照)
  • v1.4:更多排队模型(M/G/c/k 精确数值解、优先级队列)
  • v1.5:从 OpenTelemetry / Prometheus 指标草稿自动生成场景文件

社区贡献方向:新组件类型、新实例价格目录、教学场景库(经典故障模式复现)、报告主题。

📦 打包与部署指南

ScaleForge 属于脚本 / 工具库类项目,无需安装常驻服务。

跨平台单文件包

# Linux / macOS
bash scripts/build_pyz.sh
# Windows PowerShell
powershell -ExecutionPolicy Bypass -File scripts/build_pyz.ps1
# 产物 dist/scaleforge.pyz,任何装有 Python 3.8+ 的机器:python3 scaleforge.pyz ...

Wheel 包

python3 -m pip wheel . --no-deps -w dist   # 产出 py3-none-any 通用 wheel
pip install dist/scaleforge-1.0.0-py3-none-any.whl

在 CI 中运行(GitHub Actions 片段)

- uses: actions/setup-python@v5
  with: { python-version: "3.11" }
- run: python3 -m unittest discover -s tests
- run: python3 -m scaleforge analyze design.json --rps 300 --strict

兼容环境:Python 3.8 / 3.9 / 3.10 / 3.11 / 3.12,操作系统无关;内存占用 < 50MB,单次分析为毫秒级,60 秒仿真为亚秒级。

🤝 贡献指南

欢迎 Issue 与 PR!请先阅读 CONTRIBUTING.md。提交信息遵循 Angular 规范:feat: / fix: / docs: / test: / refactor:。核心约束:运行时零第三方依赖、所有解析结论必须有已知值测试或仿真对照、仿真必须可被种子复现

📄 开源协议

基于 MIT License 开源,可自由商用、修改与分发,保留版权声明即可。内置实例价格仅为参考估算,请以云厂商官网实时报价为准。


繁體中文

🔁 雙引擎交叉驗證:Erlang-C / M/M/c/K 閉式解析(毫秒級出結果)+ 純標準函式庫離散事件模擬(驗證解析結論),全程離線、零第三方相依套件。

🎉 專案介紹

ScaleForge(容量鍛造台) 是一款為後端工程師、SRE 與準備系統設計面試的開發者打造的離線容量規劃與瓶頸推演工具。你用一份 JSON 描述系統拓撲(閘道、服務、快取、資料庫、訊息佇列、Worker),它就能回答四個關鍵問題:

  1. 目前流量下,端到端 p50/p95/p99 延遲是多少?錯誤率多少?
  2. 第一個被壓垮的元件是誰?呼叫鏈上的瓶頸路徑是什麼?
  3. 流量持續上升,系統會在哪個 RPS 斷裂?距離 SLO 擊穿還剩多少餘裕?
  4. 要撐住目標流量,每個元件至少要擴到幾個副本?一個月大概要多少預算?

😮‍💨 解決什麼痛點

  • 系統設計教材多半是靜態架構圖與「加快取、上佇列」的口訣,缺乏對排隊行為的量化直覺:為什麼利用率一過 70%,p99 就開始非線性暴衝?
  • 真實壓測得先把系統寫完、部署上線,成本高、週期長,還可能打掛共用環境;
  • 紙上算容量只會「QPS ÷ 單機 QPS」,忽略排隊等待、扇出呼叫、快取穿透、逾時重試放大,結果上線即雪崩。

🌟 自研差異化亮點

  • 🧮 雙引擎互驗:閉式排隊模型(Erlang-C、有限佇列 M/M/c/K、Allen-Cunneen 通用近似、Little 定律、尾延遲反解)與獨立實作的離散事件模擬互為校驗,數字絕非「畫得好看」。
  • 🧾 Scenario-as-Code:一份 JSON 即可版控、進 Git、進 CI;--strict 可在 SLO 擊穿時以非零結束碼攔截變更。
  • 🧗 負載掃描與斷裂點偵測:自動掃描 RPS 區間,分別給出利用率上限、p99 SLO 上限、錯誤率上限,取最嚴約束做為安全水位。
  • 🩺 瓶頸根因鏈 + 擴容反解:定位入口到瓶頸的呼叫路徑,並反解各元件達成目標利用率所需的最少服務台/副本數。
  • 🌩️ 故障機制建模:有限佇列丟棄、逾時 + 有限次重試的負載放大效應(被放棄的請求仍會在下游佔用運算——這正是重試風暴的機制)、快取命中率吸收、同步/非同步扇出。
  • 📉 四種報告形態:彩色終端機報告 + ASCII 趨勢圖、機器可讀 JSON、Markdown、單檔離線 HTML 報告(手寫 SVG 圖表,完全無外部資產)
  • 📦 零相依、跨平台、單檔案:Python 3.8+ 標準函式庫即可執行;一鍵打包成 scaleforge.pyz 隨身攜帶。

💡 靈感來源

專案受近期 GitHub 熱門的分散式系統教學模擬器啟發(畫布式拖曳、拉高流量觀察排隊行為)。我們認同「以實驗取代口訣」的理念,但選擇了不同路線:CLI/程式碼優先、可重現、可進 CI、解析與模擬互驗、直接產出容量規劃結論,並補上畫布產品欠缺的 SLO 水位計算、擴容反解與成本估算。未使用其任何程式碼或素材,全部為獨立自研。

✨ 核心特性

  • 🧮 解析引擎:M/M/1、M/M/c(Erlang-C 等待機率)、M/M/c/K 有限佇列丟棄率、Allen-Cunneen 非指數服務近似、Little 定律、p50/p95/p99 尾延遲閉式反解。
  • 🎲 離散事件模擬:自寫事件迴圈:卜瓦松到達、指數/定長/Gamma 服務時間、多服務台、有界 FIFO 佇列、逾時計時器、有限重試、串行/並行扇出、快取吸收,固定隨機種子可重現。
  • 🕸️ 拓撲流量傳播:DAG 呼叫圖、依邊扇出倍數、快取穿透率、重試放大定點迭代收斂、並行取 max/串行求和的延遲合成。
  • 📈 負載掃描(Sweep):線性抬升 RPS,輸出 p99/利用率/錯誤率/有效吞吐曲線,自動標註安全水位與餘裕百分比。
  • 🩺 診斷與建議:過載、高利用率、佇列溢出、逾時風險、重試放大、快取機會等分級發現(critical / warning / ok),每條都附可執行建議。
  • 💰 成本估算:內建通用執行個體目錄(參考價,可覆寫),估算月度成本與每百萬請求成本。
  • 🖥️ 終端體驗:ANSI 彩色表格、ASCII 折線圖與迷你趨勢線,--no-color 適應管線與 CI。
  • 🧰 函式庫友善:每個引擎都是純函式 API,可直接嵌入自動化容量評審流水線。
  • 🔒 隱私安全:不發起任何網路請求、無遙測,場景資料永不離開本機;JSON 僅做結構解析,無動態執行。

🚀 快速開始

環境需求

  • Python 3.8 以上(Windows / macOS / Linux 皆可),無需安裝任何第三方套件

方式一:原始碼直接執行(建議先試)

git clone https://github.com/gitstq/ScaleForge.git
cd ScaleForge
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep --no-color

方式二:產生自己的場景範本

python3 -m scaleforge init my-system.json
python3 -m scaleforge check my-system.json
python3 -m scaleforge analyze my-system.json

方式三:單檔案 zipapp(帶著走)

bash scripts/build_pyz.sh                # Windows 請用 scripts/build_pyz.ps1
python3 dist/scaleforge.pyz analyze examples/01_monolith.json

方式四:pip 安裝為指令

pip install .
scaleforge analyze examples/03_retry_storm.json --rps 60

📖 詳細使用指南

場景檔結構

{
  "name": "my-service",
  "entrypoint": "gateway",
  "rps": 120.0,
  "slo": { "p99_ms": 400.0, "max_error_rate": 0.001, "max_utilization": 0.7 },
  "components": [
    { "name": "gateway", "kind": "gateway", "replicas": 2,
      "concurrency": 8, "service_time_ms": 3.0 }
  ],
  "edges": [
    { "source": "gateway", "target": "orders", "calls": 1, "mode": "parallel" }
  ]
}

元件欄位:kind(閘道/服務/快取/資料庫/佇列/Worker/外部服務)、replicas × concurrency=總服務台數、service_time_ms 平均處理時間(0 為純透傳節點)、service_cv 服務時間變異係數(0 定長、1 指數)、max_queue 有界佇列(-1 無界)、cache_hit 就地吸收比例、timeout_msretries 逾時與重試原則(宣告於被調端)。邊欄位:calls 扇出倍數(可為小數機率呼叫)、modesequential(延遲求和)或 parallel(取最大值)。

指令一覽

指令 用途 常用參數
init [path] 產生範例場景 --force 覆寫
check <file> 校驗場景
analyze <file> 穩態解析+診斷+成本 --rps--sim--sweep--strict--format text/json/md/html--out
simulate <file> 只跑離散事件模擬 --duration 60 --warmup 5 --seed 42
sweep <file> 只做負載掃描 --min-rps --max-rps --steps

典型情境

# A. 容量評審:給目標流量反推資源,輸出 Markdown
python3 -m scaleforge analyze design.json --rps 500 --format md --out review.md

# B. CI 容量門禁:SLO 擊穿即傳回非零結束碼
python3 -m scaleforge analyze design.json --rps 300 --strict

# C. 離線 HTML 報告(範例:docs/sample-report.html,瀏覽器直接開)
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep \
  --format html --out report.html

作為 Python 函式庫使用

from scaleforge.model import Scenario
from scaleforge.engine import analyze
from scaleforge.sweep import sweep
from scaleforge.diagnose import diagnose

scn = Scenario.load("design.json")
result = analyze(scn, rps=300)
print(result.e2e_p99_ms, result.goodput_rps, result.bottleneck)
for item in diagnose(scn, result).capacity_plan:
    print(item.component, item.required_servers, item.recommended_replicas)
print("安全水位 RPS:", sweep(scn, 50, 800, steps=30).safe_rps)

輸出解讀

util 為到達率 ÷ 總服務率,長期 ≥100% 佇列無界成長;p99 為沿關鍵路徑合成的第 99 百分位延遲;drop 為有界佇列溢出比例;retry 為重試造成的下游負載倍數;safe load 為同時滿足三條 SLO 的最大 RPS。

常見問題

  • 解析與模擬會完全一致嗎? 中低負載下均值應高度一致;尾延遲受模擬時長與種子影響有統計波動,可加大 --duration 收斂。解析負責掃描,模擬負責驗證。
  • 會真的發壓測流量嗎? 刻意不會,ScaleForge 是離線建模工具,不發任何網路封包;真實壓測請搭配 k6/wrk/Locust。
  • 服務時間怎麼估? 取線上 P50 均值當 service_time_ms,服務時間分布越不穩定,service_cv 越大;不確定就維持 1.0(指數分布為保守上界)。

💡 設計思路與迭代規劃

為什麼是「雙引擎」

閉式公式毫秒級、適合對整段流量區間掃描,但帶有分布假設;離散事件模擬不依賴閉式假設、能刻畫逾時/重試的動態過程,但有統計成本。ScaleForge 讓兩者共存:解析引擎做掃描與規劃,模擬引擎做交叉驗證,且兩套實作完全獨立,避免同一個錯誤互相背書。

技術選型理由

  • 純標準函式庫 Python:容量計算是輕量數學問題,零相依代表任何機器、任何 CI、任何離線環境都能直接執行,heapq 足以驅動事件模擬。
  • JSON 而非自訂 DSL:零學習成本、原生可 diff、可被任何語言產生。
  • 手寫 SVG 報告:不依賴 CDN 與圖表套件,離線可開、可郵件轉發,不因外連失效而白屏。

路線圖

  • v1.1:熔斷器(open / half-closed / closed)狀態機進入模擬引擎
  • v1.2:漏桶/權杖桶限流與 HPA 風格自動擴縮容模擬
  • v1.3:場景前後對照 diff(改副本數前後兩份報告自動比對)
  • v1.4:更多排隊模型(M/G/c/k 精確數值解、優先權佇列)
  • v1.5:從 OpenTelemetry/Prometheus 指標自動產生場景草稿

社群貢獻方向:新元件類型、各雲執行個體價格目錄、教學場景庫(經典故障模式復現)、報告主題。

📦 打包與部署指南

本專案屬於腳本/工具函式庫類型,無常駐服務。

# 跨平台單檔案(Linux / macOS)
bash scripts/build_pyz.sh
# Windows PowerShell
powershell -ExecutionPolicy Bypass -File scripts/build_pyz.ps1
# 通用 wheel
python3 -m pip wheel . --no-deps -w dist

相容環境:Python 3.8–3.12,作業系統無關;記憶體占用 < 50MB,單次分析毫秒級、60 秒模擬為亞秒級。CI 中可執行 python3 -m unittest discover -s tests 後以 analyze --strict 作為容量門禁。

🤝 貢獻指南

歡迎 Issue 與 PR,請先參閱 CONTRIBUTING.md。提交訊息遵循 Angular 規範:feat:fix:docs:test:refactor:。核心原則:執行階段零第三方相依、所有解析結論必須有已知值測試或模擬對照、模擬必須能以種子重現

📄 開源授權

MIT License 開源,可自由商用、修改與散布,保留版權聲明即可。內建執行個體價格僅供參考估算,請以雲端供應商官網即時報價為準。


English

🔁 Two independent engines cross-check each other: closed-form queueing analytics (Erlang-C / M/M/c/K, instant) and a standard-library-only discrete-event simulation. Fully offline, zero third-party dependencies.

🎉 Introduction

ScaleForge is a local-first capacity planning and bottleneck reasoning tool for backend engineers, SREs and system-design interview prep. Describe your topology in one JSON file — gateways, services, caches, databases, queues, workers — and it answers four questions that usually require a running production-grade load test:

  1. At the current load, what are the end-to-end p50/p95/p99 latencies and error rate?
  2. Which component breaks first, and what is the call path that leads to it?
  3. As traffic keeps growing, at which RPS does the system violate its SLOs, and how much headroom remains?
  4. To serve a target load, how many replicas does every component actually need — and what does that cost per month?

😮‍💨 The problem

  • Most system-design material is static diagrams plus rules of thumb ("add a cache", "use a queue"). There is no quantitative intuition for why p99 turns nonlinear once utilization passes ~70%.
  • Real load tests require building and deploying the system first — slow, expensive, and risky for shared environments.
  • Back-of-the-envelope math ("QPS ÷ per-node QPS") ignores queueing wait, fan-out, cache penetration and timeout-retry amplification — so the design collapses on launch.

🌟 Differentiation

  • 🧮 Dual engines, cross-validated. Closed-form models (Erlang-C, bounded M/M/c/K, Allen-Cunneen approximation, Little's law, inverse tail percentiles) and an independently written discrete-event simulator validate each other — no number is "animated to look plausible".
  • 🧾 Scenario-as-Code. One JSON file you can version, diff and gate in CI; --strict exits non-zero when an SLO is breached.
  • 🧗 Load sweeps & breaking-point detection. Ramp RPS automatically and derive three independent caps (utilization, p99, error rate); the strictest one becomes the safe load.
  • 🩺 Bottleneck root-cause chain & inverse sizing. Trace the entrypoint-to-bottleneck path and solve backwards for the minimum servers/replicas that meet your utilization target.
  • 🌩️ Failure mechanics. Bounded-queue drops, timeout + bounded-retry load amplification (abandoned calls keep consuming downstream capacity — the retry-storm mechanism), cache absorption, sequential/parallel fan-out.
  • 📉 Four report formats. Color terminal tables with ASCII charts, machine-readable JSON, Markdown, and a single-file offline HTML report with hand-written SVG charts — no external assets at all.
  • 📦 Zero dependencies, cross-platform, single-file. Python 3.8+ standard library only; build a portable scaleforge.pyz with one command.

💡 Inspiration

ScaleForge was inspired by a recently trending interactive canvas simulator for teaching distributed-system behavior. We share the "run the experiment instead of memorizing rules" philosophy, but take a different path: CLI/code-first, reproducible, CI-friendly, with analytic/simulation cross-validation and direct capacity-planning outputs — SLO safe-load computation, inverse sizing and cost estimation that canvas products do not provide. No upstream code or assets were used; this is an independent implementation.

✨ Features

  • 🧮 Analytic engine — M/M/1, M/M/c (Erlang-C wait probability), M/M/c/K bounded-queue blocking, Allen-Cunneen general-service approximation, Little's law, closed-form p50/p95/p99 inversion.
  • 🎲 Discrete-event simulation — custom event loop with Poisson arrivals, exponential/constant/Gamma service times, multi-server pools, bounded FIFO queues, timeout timers, bounded retries, sequential/parallel fan-out and cache absorption; fully reproducible via --seed.
  • 🕸️ Topology propagation — DAG call graph, per-edge fan-out, cache pass-through, fixed-point convergence of retry amplification, latency composition with parallel-max / sequential-sum semantics.
  • 📈 Sweeps — linear RPS ramps producing p99 / utilization / error / goodput curves with annotated safe load and headroom.
  • 🩺 Diagnosis — severity-ranked findings (overload, high utilization, queue overflow, timeout risk, retry amplification, cache opportunity), each with an actionable suggestion.
  • 💰 Cost estimation — built-in reference instance catalog (overridable) for monthly cost and cost-per-million-requests.
  • 🖥️ Terminal UX — ANSI tables, ASCII line charts and sparklines; --no-color for pipes and CI.
  • 🧰 Library-friendly — every engine is a plain functional API you can embed in automated capacity reviews.
  • 🔒 Privacy & safety — no network calls, no telemetry, scenarios never leave your machine; JSON is parsed structurally with no dynamic execution.

🚀 Quick Start

Requirements

  • Python 3.8+ on Windows / macOS / Linux. No third-party packages required.

Option 1 — run from source

git clone https://github.com/gitstq/ScaleForge.git
cd ScaleForge
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep --no-color

Option 2 — scaffold your own scenario

python3 -m scaleforge init my-system.json
python3 -m scaleforge check my-system.json
python3 -m scaleforge analyze my-system.json

Option 3 — portable single-file zipapp

bash scripts/build_pyz.sh          # Windows: scripts/build_pyz.ps1
python3 dist/scaleforge.pyz analyze examples/01_monolith.json

Option 4 — install as a command

pip install .
scaleforge analyze examples/03_retry_storm.json --rps 60

A 30-second tour — watch a slow database plus a 90 ms timeout and 2 retries collapse under load:

python3 -m scaleforge analyze examples/03_retry_storm.json --rps 60 --no-color
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 140 --sweep --no-color

📖 Usage Guide

Scenario schema

{
  "name": "my-service",
  "entrypoint": "gateway",
  "rps": 120.0,
  "slo": { "p99_ms": 400.0, "max_error_rate": 0.001, "max_utilization": 0.7 },
  "components": [
    { "name": "gateway", "kind": "gateway", "replicas": 2, "concurrency": 8,
      "service_time_ms": 3.0, "instance_type": "standard" }
  ],
  "edges": [
    { "source": "gateway", "target": "orders", "calls": 1, "mode": "parallel" }
  ]
}

Component fields:

Field Default Meaning
name required unique component name
kind service gateway / service / cache / database / queue / worker / external
replicas 1 replica count
concurrency 1 servers per replica; total servers = replicas × concurrency
service_time_ms 0 mean per-call service time; 0 = pass-through node (e.g. logical queue)
service_cv 1.0 coefficient of variation: 0 constant, 1 exponential, otherwise Gamma
max_queue -1 waiting-room size; -1 unbounded, arrivals are dropped when full
cache_hit 0.0 fraction absorbed locally without calling downstream
timeout_ms 0 caller timeout; enables timeout-probability modeling when > 0
retries 0 retry attempts on timeout/drop (policy declared on the callee)
instance_type auto catalog entry used for cost estimation

Edge fields: calls (downstream calls per parent call; decimals model probabilistic calls), mode (sequential sums latency, parallel takes the max).

Commands

Command Purpose Key options
init [path] write an example scenario --force
check <file> validate a scenario
analyze <file> steady-state analysis + diagnosis + cost --rps, --sim, --sweep, --strict, --format text/json/md/html, --out
simulate <file> discrete-event simulation only --duration 60 --warmup 5 --seed 42
sweep <file> load sweep only --min-rps --max-rps --steps

Recipes

# A. Capacity review: target load -> resource plan as Markdown
python3 -m scaleforge analyze design.json --rps 500 --format md --out review.md

# B. CI gate: non-zero exit (3) when SLOs are breached
python3 -m scaleforge analyze design.json --rps 300 --strict

# C. Offline HTML report (see docs/sample-report.html for a rendered example)
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep \
  --format html --out report.html

Use as a library

from scaleforge.model import Scenario
from scaleforge.engine import analyze
from scaleforge.sweep import sweep
from scaleforge.diagnose import diagnose

scn = Scenario.load("design.json")
result = analyze(scn, rps=300)
print(result.e2e_p99_ms, result.goodput_rps, result.bottleneck)
for item in diagnose(scn, result).capacity_plan:
    print(item.component, item.required_servers, item.recommended_replicas)
print("safe rps:", sweep(scn, 50, 800, steps=30).safe_rps)

Reading the output

  • util = arrival rate ÷ total service rate. ≥100% means unbounded queue growth; above your max_utilization SLO (default 70%) you get a queueing warning.
  • p99 = end-to-end 99th-percentile latency composed along the critical path; the simulation report provides an independent measured counterpart.
  • drop = bounded-queue overflow fraction; retry = downstream load multiplier caused by retries.
  • safe load = largest RPS that simultaneously satisfies utilization, p99 and error SLOs.

Demo

Offered load : 140.00 rps   Goodput: 0.00 rps   Errors: 100.0%   [SLO BREACHED]
db  database  420.00 in rps  8 servers  util 100.0%  drop 65.4%  retry 3.00x
✗ CRIT  Arrival 420.0 rps >= service capacity 145.5 rps (rho -> 100%)
⚠ WARN  Retries multiply downstream load by x3.00.

The same design is fully healthy at 60 rps but collapses at 140 rps because a slow database, a 90 ms timeout and 2 retries triple the downstream load — a textbook retry storm, visible before you deploy anything.

FAQ

  • Should analytics match the simulation exactly? Means match closely at low/medium load; tail percentiles carry statistical noise that shrinks with a longer --duration. Use analytics for sweeps, simulation for final validation.
  • Does it send real load? Deliberately not — ScaleForge is an offline modeler and never opens a socket. Pair it with k6 / wrk / Locust for real traffic.
  • How do I estimate service time? Use the production mean as service_time_ms and raise service_cv for erratic latency; when unsure keep 1.0 (the exponential distribution is the conservative bound).

💡 Design & Roadmap

Why two engines

Closed-form math is instant and ideal for sweeps but assumes distributions. Discrete-event simulation needs no closed form and captures dynamic behavior like timeouts/retries, at a statistical cost. ScaleForge keeps both: analytics for planning sweeps, simulation for verification, implemented independently so one cannot vouch for the other's bug.

Technology choices

  • Standard-library Python only. Capacity math is lightweight; zero dependencies means it runs on any machine, any CI, fully offline — heapq is all the event loop needs.
  • JSON instead of a custom DSL. No learning curve, diff-friendly, generatable from any language.
  • Hand-written SVG reports. No CDN or chart library: reports open offline, forward by email, and never white-screen on a dead external link.

Roadmap

  • v1.1 — circuit breaker state machine (open / half-closed / closed) in the simulator
  • v1.2 — leaky-bucket/token-bucket rate limiting and HPA-style autoscaling
  • v1.3 — scenario diff (before/after replica-change comparison)
  • v1.4 — richer queueing models (exact M/G/c/k numerics, priority queues)
  • v1.5 — draft scenarios from OpenTelemetry / Prometheus metrics

Contribution areas: new component kinds, cloud price catalogs, a teaching-scenario library of classic failure modes, report themes.

📦 Packaging & Deployment

ScaleForge is a script / library project — no long-running service.

# Cross-platform single-file app
bash scripts/build_pyz.sh                       # Linux / macOS
powershell -ExecutionPolicy Bypass -File scripts/build_pyz.ps1   # Windows
# Universal wheel
python3 -m pip wheel . --no-deps -w dist

Compatibility: Python 3.8–3.12, OS-independent; < 50 MB RAM, millisecond analysis and sub-second 60 s simulations. In CI, run python3 -m unittest discover -s tests, then gate with analyze --strict.

🤝 Contributing

Issues and PRs are welcome — please read CONTRIBUTING.md first. Follow Angular-style commits (feat: / fix: / docs: / test: / refactor:). Hard rules: zero runtime dependencies, every analytic result needs a known-value or DES cross-check test, simulations must be seed-reproducible.

📄 License

Released under the MIT License — free for commercial use, modification and redistribution with the copyright notice retained. Built-in instance prices are rough references; always verify against current vendor pricing.

About

⚖️ Local-first System Design Capacity Simulator — queueing analytics (Erlang-C/M/M/c/K) + discrete-event simulation, SLO planning, zero dependencies | 本地优先的系统设计容量模拟器,排队论解析×离散事件仿真双引擎

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages