v0.34.0_p1

This commit is contained in:
Mateusz Gruszczyński committed 2026-10-17 22:33:00 +02:00
1 parent 00f29f92c8
commit 0a8bc6f040
21 files changed
+672 -144

No files matched your search

+93
View File
@@ -0,0 +1,93 @@
# RustProxy 0.34.0 — poprawki cache, transformacji i kontrola RPS
Status: **zmodyfikowane źródła, niekompilowane lokalnie** (brak `cargo` i `rustc`). Numer wersji: 0.34.0.
## Co odtworzono na binarce użytkownika
Uruchomiono binarkę Linux ELF w izolowanej konfiguracji z lokalnym origin HTTP, z włączonym cache, transformacją CSS, `max_ttl_seconds=86400`, diagnostyką i API administracyjnym. HTTP/1.1 localhost, pełne GET, brak kontaktu z witryną produkcyjną.
| Odpowiedź | Pierwszy GET | Drugi GET | Liczba pobrań z origin |
|---|---|---|---|
| `/normal.css` | MISS | HIT | 1 |
| `/aged.css` | MISS | MISS | 2 |
| `/br.css` | MISS | HIT | 1 |
| `/aged-br.css` | MISS | MISS | 2 |
| `/private.css` | MISS | MISS | 2 |
| `/no-store.css` | MISS | MISS | 2 |
Zwykły CSS i skompresowany Brotli dostają HIT. Warianty z `Age: 1553483` mają `MISS → MISS` mimo `Cache-Control: public, max-age=2592000`. Przypadki `private` / `no-store` słusznie nie trafiają do cache. Zmiana keep-alive vhosta nie usuwała poprawnie zachowanego obiektu. `expose_only_hits=true` celowo ukrywa nagłówki na MISS.
## Główna przyczyna i poprawka
W `src/cache/policy/response.rs` obowiązywał wzór `ttl = min(origin_max_age, local_max_ttl)` oraz `remaining = ttl - corrected_age`. To jest sprzeczne z zadaniem lokalnego limitu: świeżość w origin nadal trwa, ale CDN `Age > local_max_ttl` dawał sztuczne 0 sekund lokalnej świeżości.
Poprawiony wzór:
```text
corrected_initial_age = max(apparent_age, upstream_age + response_delay)
remaining_origin_freshness = max(0, origin_max_age - corrected_initial_age)
remaining_local_freshness = min(remaining_origin_freshness, local_max_ttl)
entry_fresh_until_age = corrected_initial_age + remaining_local_freshness
```
Przykład z przesłanych nagłówków: wiek upstream 1 553 483 s = prawie 18 dni. Pierwotna świeżość 2 592 000 s (30 dni), więc pozostało około 12 dni w origin. Po naprawie RustProxy będzie mógł przechować świeżą odpowiedź przez lokalny limit (domyślnie 86 400 s = 1 dzień). Nagłówek Age nadal będzie około 1,55 mln sekund i będzie rósł na HIT — to poprawne.
`Age` nie wynika z `Last-Modified: 2016`. Najczęściej jest przekazany przez upstream/CDN, a stara data `Date` też mogłaby podnieść apparent_age. Rozróżnienie: `Age` = HTTP wiek całkowity; `resident_age_seconds` = pobyt w HOT/COLD.
## HOT RPS i panel
1. HOT HIT nie wyjmuje już i nie wkłada od nowa wpisu oraz indeksu `Vary`, tylko aktualizuje licznik HIT i kolejność LRU w miejscu. Zmiana ma zmniejszyć alokacje i krytyczną sekcję; **zysk RPS jeszcze niezmierzony**.
2. Panel Cache ma osobne kolumny **Age** i **Czas w RustProxy**. API `dashboard.objects[]` dodaje `resident_age_seconds` także dla COLD. Pozostałe nazwy pól nie zostały zmienione.
3. Licznik `x-cache-hits` dotyczy konkretnego aktualnego wpisu. Gdy obiekt zostanie wyparte z HOT (limit wpisów/pamięć), usunięty lub zastąpiony po MISS, licznik restartuje. W próbce użytkownika TTL wynosił około 604 tys. s (7 dni), więc późniejszy MISS po ~4 minutach **nie wynikał z normalnego wygaśnięcia TTL**. Konkretnej przyczyny epizodu nie można ustalić bez trendów `evictions`, `purges`, `hot_demotions`, `cold_hits`, kluczy/Vary oraz zmian konfiguracji.
4. Brak `x-cache` na MISS jest oczekiwany, gdy włączono **nagłówki diagnostyczne tylko na HIT**. Brak wpisu w API może mieć inne przyczyny (np. cache-control `private`, `no-store`, brak polityki origin, limit obiektu) i nie należy ich obchodzić na siłę.
5. Nie zmieniano uprawnień, `private`/`no-store`, kluczy Vary, TTL po stronie origin ani zasad selektywnej invalidacji.
## Wynik symulacji TTL
Wykonano **100 000 deterministycznych scenariuszy**. Dla każdego sprawdzono: po naprawie lokalna świeżość nie przekracza `local_max_ttl` ani świeżości pozostałej w origin.
| Scenariusz | Stary pozostały TTL | Po poprawce (symulacja) |
|---|---:|---:|
| Age = 1 553 483, local cap 1 dzień | 0 s | 86 400 s |
| Age = 1 553 483, local cap 7 dni | 0 s | 604 800 s |
| Origin kończy świeżość za 10 s | 0 s | 10 s |
| Origin jest już nieświeży | 0 s | 0 s |
W symulacji 33 387 / 100 000 losowych przypadków stara polityka błędnie dawała zero zamiast dodatniego TTL. **To nie jest procent regresji w realnym ruchu**, a wynik losowania parametrów testowych.
## Nginx — rzeczywiste pomiary starej binarki
Archiwalne wyniki samej binarki `rust-proxy 0.34.0` na tym środowisku (Linux, 4 vCPU, HTTP/1.1 loopback, ApacheBench, 64 połączenia, cache OFF, 3 powtórzenia), z nginx 1.26.3. Brak miarodajnego benchmarku **nowych źródeł** przed ponowną kompilacją.
| Endpoint | RustProxy RPS (mediana) | nginx RPS (mediana) | RustProxy / nginx |
|---|---:|---:|---:|
| proxy 1 KiB | 10,544 | 58,709 | 18.0% |
| proxy 64 KiB | 7,893 | 17,358 | 45.5% |
| proxy 1 MiB | 1,010 | 1,666 | 60.6% |
| www 1 KiB | 11,984 | 71,318 | 16.8% |
| www 64 KiB | 9,224 | 26,600 | 34.7% |
| www 1 MiB | 1,264 | 1,098 | 115.2% |
Ograniczenia porównania: ApacheBench może limitować klienta; wyniki nie reprezentują TLS/H2/H3 ani ruchu produkcyjnego. **Nie wolno tych RPS przypisywać nowej rewizji.**
## Zestaw testów dla nowej kompilacji
```bash
CARGO_INCREMENTAL=0 cargo test --locked --lib
CARGO_INCREMENTAL=0 cargo build --release --locked
python3 scripts/tests/cache_age_policy_034_model.py
python3 scripts/tests/cache_age_transform_034_live.py --binary target/release/rust-proxy --output /tmp/cache-test-034
python3 scripts/tests/cache_scope_034_static_test.py
python3 scripts/tests/proxy_hotpath_034_static_test.py
python3 scripts/tests/sendfile_034_static_test.py
```
Do testów jednostkowych dodano Age, transformowane CSS/HOT, democję do COLD i odczyt COLD po restarcie, logikę LRU/HIT oraz kontrolę zakazów `private`/`no-store`. Test lokalny sprawdza CSS/Brotli, origin count, API, keep-alive config i ukryte nagłówki. Test po kompilacji bez przełącznika `--expect-old-age-bug` ma wykazać `MISS → HIT` dla Age/Brotli. Na starej binarce odtwarzanie regresji przechodzi z `--expect-old-age-bug`.
Kontrole wykonane na źródłach: źródłowe testy cache scope, proxy hotpath, sendfile, składnia JS, parsowanie tłumaczeń. **Nie uruchomiono testów Rust ani benchmarków poprawionej binarki** — środowisko nie ma `cargo/rustc`.
## Następny pomiar po kompilacji
Porównać tę rewizję 0.34.0 z poprzednią 0.34.0 oraz nginx dla 1 KiB / 64 KiB / 1 MiB; osobno cache OFF, HOT HIT i transformacja/Brotli. Raportować RPS, p95/p99, procesor, RSS, nowe TCP, `cache.evictions` i `cache.purges`; nie modyfikować ustawień cache podczas benchmarku.
Uwaga: `curl -I -X GET` miesza zachowanie HEAD i GET; do testów reprezentacji zalecane `curl -sS -D - -o /dev/null URL`.