CPU / TCP In Entwicklung
Von 1 auf 3 und dann auf 10 Knoten
Beginnen Sie mit einem Shard und behalten Sie dieselbe Client-API. Der CPU/TCP-Pfad benötigt derzeit koordinierte Betriebsschritte. Ein gestarteter Server tritt keinem Cluster automatisch bei: Jeder ShardedClient benötigt den vollständigen Routen-Snapshot.
Das Beispiel betreibt 1, 3 und 10 localhost-TCP-Server in einem Prozess. Es prüft Softwareverträge, keine zehn physischen Hosts, Produktionsverfügbarkeit, GPU-Kapazität oder Leistung. RDMA, GDS, BlueField-3 und reale Engines bleiben NOT_RUN_HARDWARE.
Topologie
| Stufe | Stabile Shard-IDs | Beispieladressen | Epoch-Bedingung |
|---|---|---|---|
| 1 Knoten | 0 | 10.0.0.11:9735 | Tatsächliche Anfangs-Epoch E |
| 3 Knoten | 0–2 | 10.0.0.11–13:9735 | Jeder Knoten über dem bisherigen Maximum |
| 10 Knoten | 0–9 | 10.0.0.11–20:9735 | Jeder Knoten über dem bisherigen Maximum |
Ersetzen Sie die Beispieladressen durch erreichbare Endpunkte. Jeder Server benötigt ein unabhängiges Datenverzeichnis und eine eindeutige stabile Shard-ID in der Client-Konfiguration. Es gibt kein --shard-id, --join, Seed-Discovery, Quorum oder Replikationsfaktor im Server. Rendezvous-Hashing über die vollständige CacheIdentity bestimmt genau einen Eigentümer.
Lokales Beispiel
Nach den Voraussetzungen im Schnellstart führen Sie die verlinkte Quellversion aus. Das Beispiel erstellt temporäre Stores, stoppt und joint alte Server, erhöht alle Epochs, ersetzt alle Routen, verwirft alte Sessions und prüft Lookup / Put / Commit / Get / Drained-Freigabe pro Shard. Es entfernt seine temporären Verzeichnisse.
cargo run -p gpucache-transport --example scaling_smoke
cargo test -p gpucache-transport --example scaling_smokeAuszug aus einem erfolgreichen Lauf. Die vollständige Ausgabe prüft alle Shards der jeweiligen Stufe: IDs 0, 0–2 und 0–9. Das sind Korrektheitsprüfungen, keine Leistungsmessungen.
status=SCALING_SMOKE_OK
topology=SINGLE_PROCESS_LOCALHOST
stage_shards=1 store_epoch=1 local_revision=1
stage_shards=3 store_epoch=2 local_revision=2
stage_shards=10 store_epoch=3 local_revision=3
per_shard_roundtrips=14
stale_sessions=REJECTED
automatic_payload_migration=NONE
durability_replication=NONE
hardware=NOT_RUN_HARDWARE
performance=NOT_A_PERFORMANCE_RESULTEinen Knoten starten
Dieser Befehl startet einen einzelnen FileStore auf Loopback. Der öffentliche Test-Fingerprint ist keine Produktionskennung. Verwenden Sie außerhalb lokaler Tests eigene Zugangsdaten und Richtlinien. Konfigurieren Sie ShardedClient mit ID 0, Adresse und tatsächlicher Epoch aus dem TCP-Handshake. Die Lease/Session-API hält Put und Commit beim gewählten Eigentümer.
cargo run -p gpucache-transport --bin gpucache-tcp -- serve \
--data-dir ./data/shard-0 --bind 127.0.0.1:9735 \
--tenant 1 --trust 1 \
--fingerprint 0000000000000000000000000000000000000000000000000000000000000001Remote nur im isolierten vertrauenswürdigen Netz binden, etwa mit --bind 10.0.0.11:9735 --allow-remote. Das aktiviert weder TLS noch kryptografische Peer-Authentisierung. Der Fingerprint ist eine Bearer-ähnliche Kennung über Klartext-TCP. Die CLI startet nur den Server; der Client wird in Anwendungscode konfiguriert.
Client vor der ersten Stufe konfigurieren
Wählen Sie beim Erstellen des Clients die Grenzen für die endgültige Topologie. Der Anwendungscode muss den authentifizierten Kontext und geprüfte Anfangsendpunkte bereitstellen. replace_routes ändert ClientLimits nicht. Diese Konfiguration erlaubt in allen Stufen zehn Shards mit je einer Verbindung:
use gpucache_transport::{ClientLimits, ShardedClient};
let limits = ClientLimits {
max_shards: 10,
max_connections: 10,
max_connections_per_shard: 1,
max_frame_bytes: 2 * 1024 * 1024,
..ClientLimits::default()
};
let client = ShardedClient::new(auth, endpoints, limits)?;Das Standardlimit pro Shard beträgt 4 Verbindungen. Nur max_connections auf 3 zu senken wäre damit ungültig. Jeder Server akzeptiert standardmäßig 16 Verbindungen über alle Clients zusammen; jeder Clientprozess besitzt einen eigenen Pool. Planen Sie die Gesamtnutzung.
Der CLI-Server begrenzt den Frame-Body auf 2 MiB; max_frame_bytes oben entspricht diesem Wert. Frame-Grenzen werden nicht ausgehandelt. Stimmen Sie Client und Server aufeinander ab. Das eigenständige Beispiel scaling_smoke verwendet dagegen auf beiden Seiten die passenden Bibliotheksstandardwerte von 1 MiB.
Ein neuer Client beginnt unabhängig von den tatsächlichen Store-Epochs mit lokaler Revision 1. Lesen Sie nach dem koordinierten Serverwechsel seine aktuelle Revision und rufen Sie client.replace_routes(revision, endpoints) mit dem vollständigen Snapshot auf. Revisionen gelten pro Client; sie sind weder Store-Epochs noch gemeinsame Konsens-Terme.
Von 1 auf 3
- Neue Shard-IDs 1 und 2 mit getrennten Verzeichnissen, gleicher Tenant/Trust-Policy und erreichbaren Adressen vorbereiten. Die vor der ersten Stufe gewählten Clientgrenzen verwenden und Server-, Pin-, Byte- und Retry-Budgets prüfen.
- Alle Clients pausieren und neue Lookup/Get/Put/Commit-Aufträge stoppen. Transfers abschließen und Pins nach bestätigtem Abschluss mit Drained freigeben. Lease-Ablauf beweist keinen Drain. Offene Writes abschließen oder abbrechen und einzäunen; alte Leases nicht übernehmen.
- Alte Server samt Workern stoppen und joinen oder extern nachweisbar gegen weitere Lese- und Schreibzugriffe einzäunen. replace_routes verändert nur den lokalen Client; es führt kein Remote-Fencing aus. Ohne Nachweis keine neue Route veröffentlichen.
- Alle Verzeichnisse exklusiv vorbereiten, sodass der nächste Handshake jedes Servers eine Epoch über dem bisherigen Maximum meldet. Alte Stores neu starten, neue Stores nach Bedarf initialisieren und erneut öffnen. Vor Freigabe alle tatsächlichen Epochs prüfen.
- Einen vollständigen Snapshot für IDs 0, 1 und 2 mit tatsächlichen Adressen und Epochs erstellen. Je pausiertem Client let revision = client.stats().revision; lesen und client.replace_routes(revision, endpoints) aufrufen. Ablehnungen behandeln und keine bloße Änderungsliste senden. Erst fortfahren, wenn alle erforderlichen Clients denselben vollständigen Snapshot angenommen haben.
- Nach dem Wechsel eine neue Session für neue logische Arbeit beziehen. Innerhalb einer gültigen Epoch bleiben Commit/Get/Release einer Generation auf dem ursprünglichen Shard und seiner Epoch; generationbasierte Folgeoperationen nicht neu routen. Eingezäunte Arbeit verwerfen, ihre Epoch nicht umschreiben. Umverteilte Identitäten werden nicht automatisch migriert: bei Miss/Fehler neu berechnen und explizit zurückschreiben. Optionale Cold-Restores bleiben außerhalb des heißen Pfads.
Ein frischer FileStore beginnt bei 1; erneutes Öffnen eines vorhandenen Verzeichnisses erhöht um 1. Es gibt weder --epoch noch eine Admin-Epoch-RPC. War das Maximum 1, benötigen auch neue Knoten mindestens 2; war es 7, benötigen alle mindestens 8. Das Beispiel öffnet Stores exklusiv und begrenzt oft erneut. Im Betrieb ist entsprechende Orchestrierung erforderlich. MANIFEST niemals manuell ändern.
Von 3 auf 10
Für IDs 0–9 denselben Ablauf wiederholen: pausieren → drain → stoppen/fencen → Epoch vorbereiten → vollständige Routen → prüfen → fortsetzen. Nach überall 1 und überall 2 folgt im Beispiel 3; im Betrieb zählt das beobachtete Maximum, nicht die Knotenzahl. Die beim Erstellen des Clients vorgesehenen Grenzen verwenden; Routenwechsel ändern sie nicht. Tenant-, Retry-, Pin/Region-, Frame-, Speicher- und Plattenbudgets je Shard planen.
Clients greifen direkt auf Eigentümer zu. ShardDirectory hält begrenzte Metadaten, keinen zentralen Payload-Cache. Knotenausfall ist ein Miss, kein Replikat-Failover. Drei Knoten bilden kein Quorum; zehn belegen keine Eignung für 10.000 GPUs. Verteilung und Kapazität müssen mit der eigenen Last gemessen werden.
Prüfen und zurückkehren
- Commit, stabile IDs, Adressen, tatsächliche Epochs und vollständige Client-Snapshot-Version protokollieren. Doppelte IDs oder Endpunkte ausschließen.
- Je Shard Lookup → Put → Commit → Get, Bytevergleich und Drained-Freigabe prüfen; fremde Tenants/Identitäten dürfen nicht treffen. Generationen sind shardlokal: ID und Epoch mitführen.
- Alte Sessions/Leases müssen abgewiesen werden; offene alte Writes dürfen nicht in die neue Mitgliedschaft committen. Testweise einen Eigentümer stoppen und Miss/Timeout → Neuberechnung prüfen.
- Client-Statistik und Drain/Quarantine/Fence-Berichte beobachten. Logische Deskriptorbytes von Wire-Bytes trennen; Quotenfehler, Retries und Verbindungen prüfen. CPU-Regression ist keine reale Mehrhost-Qualifikation.
- Bei Fehlern pausiert bleiben. Snapshot reparieren oder mit erneutem Stop/Fence und höheren Epochs zur alten Knotengruppe zurückkehren. Alte Epochs, Snapshots und Leases niemals reaktivieren. Heiße Daten dürfen neu berechnet werden.
python3 scripts/ci/vm_regression.py --profile cpu --offline \
--output artifacts/scaling-cpuQuellen
Maßgeblich sind Runbook und ausführbares Beispiel. Es gibt keinen fertigen Clustermanager, keine Online-Migration, keine Verfügbarkeitsgarantie für Rolling-Upgrades und keine Produktionsqualifikation mehrerer physischer Hosts.