85 lines
4.6 KiB
Markdown
85 lines
4.6 KiB
Markdown
# RustProxy 0.34.0 — reverse-proxy hot-path candidate
|
|
|
|
## What was changed
|
|
|
|
1. **Routes:** `Snapshot.routes` and `fallbacks` now hold
|
|
`Arc<CompiledRoute>` handles. The same compiled location is shared across
|
|
hostname aliases. `observe` resolves vhost/location once from the accepted
|
|
listener/TLS-state and stores a request-local handle. `forward_request`
|
|
consumes the same immutable snapshot/route; internal error fallbacks still
|
|
resolve the explicitly configured named location independently.
|
|
2. **Host matching:** wildcard candidate strings are generated lazily only
|
|
after an exact host failed, without changing longest-specific-suffix order.
|
|
3. **LB:** single-backend non-cookie pools use a direct admitted lease without
|
|
temporary candidate vectors or scheduler mutex. Multi-backend weighted
|
|
round-robin retains its ordering and mutex; least-connection/traffic,
|
|
adaptive, IP hash and cookie-affinity retain their behavior. IP hash avoids
|
|
repeated canonicalization/temporary `format!` strings for each candidate.
|
|
4. **Health:** a `healthy_cached` atomic allows checking healthy backends
|
|
without the health mutex; all state transitions remain inside the existing
|
|
state machine, including passive quarantine and half-open recovery.
|
|
Resolved active/passive per-member policies are held in shared immutable
|
|
`Arc` handles so a new request lease does not deep-clone health paths,
|
|
headers or optional host strings.
|
|
5. **Fallback/retry:** request body+HeaderMap replay templates are made only
|
|
for configured error fallbacks. Retry headers are cloned only for eligible
|
|
safe replay requests where another member or H2 graceful close makes retry
|
|
possible; writes, streaming bodies and WebSockets are not replayed.
|
|
6. **Telemetry:** three per-request mutex-backed scalar tags are now atomic;
|
|
their original event strings and `Option<bool>` log fields are decoded at
|
|
exchange completion. Request ID, method, host and path are moved into the
|
|
terminal log record instead of deep-cloned in Drop; the traffic sample
|
|
still receives its own required copies. Logs avoid a broadcast clone if
|
|
there are no subscribers, preserving history, sink and counters.
|
|
|
|
## Preserved boundaries
|
|
|
|
All vhost, ACL, GeoIP, Basic Auth, Tinyauth, WebSocket, retry, cache,
|
|
transform, compression, log, metrics, `sendfile`, PHP-FPM, HTTPS/H2/H3 and
|
|
admin panel configuration paths are intended to remain compatible. Defaults
|
|
and SQLite schema are unchanged; no new performance toggle was added. The
|
|
optimization reuses route objects within one immutable snapshot but does not
|
|
allow stale snapshot cache fills (existing revision ticket barrier remains).
|
|
Sticky cookies deliberately retain the general selection path, and upstream
|
|
request-count recycling is unchanged (default 25,000 per generation).
|
|
|
|
## Locally executed checks vs required checks
|
|
|
|
- **Executed locally:** scoped-cache/sendfile/hot-path *source-only* guards,
|
|
Python syntax, SQLite migration and upgrade preservation tests, selected JS
|
|
panel scripts and simulated editor tests. These do **not** prove Rust builds.
|
|
- **Prepared, NOT executed:** Rust unit tests for shared routing, single-member
|
|
LB capacity/health, passive ejection/recovery, atomic log fields, retained
|
|
sendfile, cache and protocol behavior.
|
|
- **Unmeasured:** 0.34.0 requests/sec, latency, CPU cost, memory and nginx gap.
|
|
Do not infer a throughput gain from fewer source-code locks/allocations.
|
|
|
|
## Build and acceptance
|
|
|
|
Run on the intended Linux builder with exactly the same compiler, dependencies,
|
|
release flags and workload as the 0.33.8 reference:
|
|
|
|
```bash
|
|
./dev.sh doctor
|
|
./dev.sh check
|
|
CARGO_INCREMENTAL=0 ./dev.sh test
|
|
CARGO_INCREMENTAL=0 cargo build --release --locked
|
|
python3 scripts/tests/proxy_hotpath_034_static_test.py
|
|
python3 scripts/tests/cache_scope_034_static_test.py
|
|
python3 scripts/tests/sendfile_034_static_test.py
|
|
python3 scripts/tests/dashboard_presets_sql_test.py
|
|
python3 scripts/tests/upgrade_performance_test.py
|
|
```
|
|
|
|
Next run `scripts/performance/regression.py`, `lb_regression.py`,
|
|
`transport_regression.py` and `concurrency_regression.py` against both binary
|
|
versions. After functional acceptance, run the paired
|
|
`scripts/performance/benchmark.py` suite against the unmodified baseline,
|
|
this candidate and nginx; use the instructions in
|
|
`scripts/performance/README.md` including separate CPU affinities.
|
|
|
|
Measure RPS/p95/p99, CPU microseconds per request, RSS, FDs, pool rotations,
|
|
health transitions, cache HIT ratio and logger drops. For each payload report
|
|
`(0.34.0 RPS / 0.33.8 RPS - 1)*100` and `0.34.0 RPS/nginx RPS*100` from real
|
|
medians. A source-only revision is **not production-accepted**.
|