Skip to content

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Oct 05:30
· 41 commits to main since this release

ONRouter 1.0.0 — the first release whose deliverable is "run it in production", not just "speak the config": CPU affinity, outage resilience, canary splitting, a WASM plugin host, CI, a 21-minute soak and two handbooks.

What's new

CPU affinity — worker_threads + worker_cpu_affinity

worker_threads N; sizes the runtime, and worker_cpu_affinity auto|off|<hex masks>; pins each
worker to a core or a core set: Linux sched_setaffinity, Windows SetThreadAffinityMask, and on
macOS — where no hard thread affinity exists — the gateway says so instead of pretending. Masks
rotate when there are more cores than workers, and -t prints the per-thread plan before the
process ever accepts a connection, so the binding is reviewable in code review rather than
guessed from top.

Resilience — circuit_breaker and lazy_rejoin

  • circuit_breaker errors=… window=… open=…; adds the closed → open → half-open machine on top of
    the existing passive max_fails/fail_timeout removal. Failures count consecutively inside the
    window
    : one success in between resets the tally.
  • lazy_rejoin <interval>; makes an ordinary user request the recovery probe. A dead backend is
    carried by the remaining servers, the next real request doubles as the trial, and a success puts
    the node back — no separate health-check traffic to budget for.
  • Metrics: onrouter_upstream_server_available now reports what the scheduler may actually pick
    (manual down, passive removal, open circuit), while onrouter_upstream_server_healthy stays
    purely the active check verdict — with no health_check configured it never leaves 1, which is
    exactly why the alerting guidance moved to available. Also new:
    onrouter_upstream_lazy_probes_total, onrouter_upstream_circuit_state,
    onrouter_upstream_circuit_trips_total.

Canary / grey release

canary $var "<sticky key>" { cookie …; header …; arg …; ua ~* …; os …; percent …; default …; }
selects a whole declared upstream per request — first match wins, and the sticky key keeps one user
on one version instead of bouncing between two. $proxy_split / $proxy_split_served plus
proxy_split_failover on|off|http://target turn a cross-version failover into a visible ledger line
rather than a silent 200, and the response cache is keyed by the branch that served it.

WASM gateway plugins

wasm_plugin <name> <file.wat|file.wasm> [fuel=…] [memory=…]; plugged into access_by_wasm,
header_filter_by_wasm and body_filter_by_wasm. A small stable host ABI exposes request/response
headers, status and body; fuel and a memory cap bound a bad module's blast radius, and traps fail
closed — a broken plugin cannot quietly pass traffic through unmodified.

Verification

  • cargo test --workspace → 482/482 (469 onrouter-server + 13 onrouter-config);
    cargo clippy --workspace --all-targets → no errors.
  • Five real-traffic E2E suites → 145/145: canary_e2e 22/22, wasm_e2e 23/23,
    resilience_e2e 17/17 (passive removal, lazy rejoin driven by a real request, circuit
    open → half-open → recovered, server_available), affinity_e2e 7/7, proxy_split_e2e 76/76.
  • conf/tutorial_full.conf end to end → 33/33 (static, canary conditions/percent/stickiness,
    proxy path rewrite, cache MISS→HIT, WASM, Lua shared dict, circuit 502 + half-open recovery,
    lazy rejoin).
  • 21-minute soak: PASS — 2,591,305 requests, 0 failures, 20.92 min, 2064.7 req/s, backend
    hits 1,963,093; private memory 20.11 → 21.97 MiB (+1.86 MiB, slope +0.067 MiB/min against a
    1 MiB/min gate), peak 22.15 MiB. An earlier run of the same configuration added +2.19 MiB over
    2,787,193 requests, so the growth tracks warm-up, not elapsed requests.
  • tools/release_verify.py on the extracted package → 26/26, including the front_proxy
    recognise-but-do-not-trust split and the provider-name grep over the packaged binary
    (controls front_proxy 49 / auto_trust 10).
  • GitHub Actions CI on this commit: unit + clippy + the five suites, success.

Downloads / assets

Per-platform archives built by release.yml (onrouter + orr-gencert, plus SHA256SUMS.txt).
Note the honest gap: those workflow assets still carry only the two executables. The runnable
directory — conf/*.conf, the wasm/wasm_static/soak_static trees, lua/, public/, both
docs, and a certs/ pair generated at package time so a fresh extract passes
onrouter -t -c conf/onrouter.conf — is what build-release.sh / build-release.ps1 produce in
the tree; wiring release.yml to that same staging is the follow-up for the next tag.

Documentation

  • docs/OPERATIONS.md — the operator half: every 1.0 directive with its default and the failure
    it guards against, ports/TLS/cert placement, affinity and topology reading, resilience and canary
    wiring, cache/Lua/WASM limits, metric families with the alerts that use server_available,
    the -t contract, hot reload, upgrade/rollback (binary hot upgrade via USR2 is still not
    implemented — roll or blue-green), and the pre-release checklist.
  • docs/TUTORIAL.md — the build-it-up half: conf/tutorial_hello.conf to
    conf/tutorial_full.conf, feature by feature, with the commands and the metrics that prove each
    step actually took.

中文摘要

1.0.0 把“能跑配置”升级成“能上线”:worker 线程绑定 CPU 核心(Linux/Windows 生效,macOS 明确说明不支持,
-t 会打印每线程的绑定计划);circuit_breaker 熔断叠加原有被动摘除,lazy_rejoin 让真实用户请求充当
恢复探针,宕机后端由其他服务器分担、恢复后自动加回;canary 按 cookie / header / 参数 / UA / 系统 /
百分比把整条 upstream 版本发给用户,粘性键保证同一人不来回跳版本,跨版本 failover 在账本里可见;
wasm_plugin 在 access / header_filter / body_filter 三个相位接管网关,带 fuel 与内存上限,出错一律 fail-closed。
新增 onrouter_upstream_server_available 表达“此刻可被调度”,与只反映主动健康检查的 server_healthy 分工。
验证:单元 482/482,五组真实流量 E2E 145/145,教程配置端到端 33/33,发布包 release_verify 26/26,
21 分钟压测 PASS(2,591,305 请求、0 失败、2064.7 req/s,私有内存 +1.86 MiB、斜率 +0.067 MiB/min)。
运维手册与使用教程分别在 docs/OPERATIONS.md、docs/TUTORIAL.md。

Full Changelog: v0.7.0...v1.0.0