Refs über Nodes hinweg
In einem Single-Node-System ist ein ActorRef ein direkter
In-Memory-Handle. In einem geclusterten System kann ein ActorRef
auf einen Actor auf jedem Node zeigen — und derselbe tell
funktioniert auf gleiche Weise:
const remote: ActorRef<Msg> = /* Ref auf einen Actor auf einem anderen Node */;remote.tell({ kind: 'do-it' });// → serialisiert, über den Cluster-Transport gesendet, in die Remote-Mailbox zugestelltDas Framework versteckt die Netzwerkschicht. Aber zu verstehen, wie das funktioniert, hilft, wenn etwas schiefläuft (Nachrichten verschwinden, Latenz schießt hoch, Refs lassen sich nicht auflösen).
Das Pfad-mit-Host-Format
Abschnitt betitelt „Das Pfad-mit-Host-Format“Der Pfad eines rein-lokalen Refs sieht so aus:
actor-ts://my-app/user/api/sessions/user-42Ein Cluster-fähiger Ref enthält den host:port seines besitzenden Nodes:
actor-ts://my-app@10.0.0.5:2552/user/api/sessions/user-42| Segment | Was es ist |
|---|---|
actor-ts:// | Das Schema — wie bei lokalen Pfaden. |
my-app | Der System-Name des Clusters. |
@10.0.0.5:2552 | Die Adresse des Nodes, vergeben bei Cluster.join. |
/user/api/sessions/user-42 | Der Actor-Pfad innerhalb dieses Nodes, gleicher Aufbau wie ein Single-Node-Pfad. |
Das Host-Fragment sagt der lokalen Runtime, welcher Node diesen
Actor hostet. Wenn du einem Remote-Ref ein tell schickst, macht
das Framework:
- Liest den host:port aus dem Pfad des Refs.
- Schlägt die Verbindung des Cluster-Transports zu diesem Node nach.
- Serialisiert die Nachricht + die Lokalpfad-Segmente des Refs.
- Schreibt einen Wire-Frame.
- Der empfangende Node deserialisiert; löst lokal die
Pfad-Segmente zu einem echten Actor auf; macht ein
tellauf den lokalen Ref.
Wie Refs über die Leitung wandern
Abschnitt betitelt „Wie Refs über die Leitung wandern“In einer Nachricht serialisiert ein ActorRef-Feld als der
Pfad-mit-Host-String. Auf dem empfangenden Node rekonstruiert
der Deserializer einen RemoteActorRef, der zurück auf den
Originalknoten zeigt:
type GetMsg = { kind: 'get'; replyTo: ActorRef<number>; // ← serialisiert als Pfad-String};
remoteRegistry.tell({ kind: 'get', replyTo: this.context.self, // → "actor-ts://my-app@10.0.0.3:2552/user/asker"});Der empfangende Node sieht replyTo als RemoteActorRef, der auf
10.0.0.3:2552/.../asker zeigt. Ein tell darauf läuft umgekehrt
durch dieselbe Encoding-und-Transport-Maschinerie.
Das bedeutet, dass Request/Response zwischen Actors auf verschiedenen Nodes einfach funktioniert — die Antwort reist über den Cluster-Transport zurück zum ursprünglichen Anfrager.
Der Cluster-Transport
Abschnitt betitelt „Der Cluster-Transport“Der Transport (TCP per Default, In-Memory in Tests) trägt:
- Cluster-Steuerverkehr — Gossip, Heartbeats, Downing-Signale.
- Envelope-Verkehr — deine
tells, in einen Routing-Envelope gewickelt.
Beide teilen sich dieselbe TCP-Verbindung pro Peer-Paar. Das Framework multiplext sie; du siehst diesen Unterschied nicht.
Siehe Transports für die TCP- und In-Memory-Implementierungen.
Einen Remote-Ref per Pfad auflösen
Abschnitt betitelt „Einen Remote-Ref per Pfad auflösen“import { ActorSelection } from 'actor-ts';
const remote = await system.actorSelection( 'actor-ts://my-app@10.0.0.5:2552/user/api/sessions/user-42',).resolveOne(5_000);
remote.tell({ kind: 'do-it' });actorSelection parst den Pfad-mit-Host; resolveOne gibt einen
RemoteActorRef zurück, dem du tell schicken kannst. Nützlich,
wenn:
- Der Standort des Ziels per Konvention bekannt ist (ein bekannter Sharding-Pfad oder Singleton-Proxy).
- Eine Nachricht einen Pfad-String enthält (z. B. aus einem HTTP-Request).
Für Routine-Cluster-Arbeit hältst du normalerweise einen Ref aus
der eigenen Maschinerie des Clusters (Sharding-Region,
Singleton-Proxy, Event-Stream-Subscriber) — actorSelection ist
der Lookup-Notausgang.
Was passiert, wenn der Remote-Node verschwindet
Abschnitt betitelt „Was passiert, wenn der Remote-Node verschwindet“const remote: ActorRef = /* auf einem Node, der den Cluster gerade verlassen hat */;
remote.tell({ kind: 'do-it' });// → Nachricht landet in Dead Letters; Sender sieht den Fehler nichtEin tell an einen Remote-Ref auf einem gestoppten/unerreichbaren
Node:
- Das Framework versucht, auf den Transport zu schreiben.
- Der Transport sieht keine lebendige Verbindung (oder eine im halb-geschlossenen Zustand).
- Die Nachricht wird zu Dead Letters fallen gelassen.
Zwei Wege, das zu erkennen:
context.watch(remoteRef)— eineTerminated-Benachrichtigung empfangen, wenn der Remote-Actor stoppt oder der Remote-Node unerreichbar+downed wird. DasTerminated.addressTerminated-Flag unterscheidet “Actor gestoppt” von “Node verloren”.- Cluster-Events abonnieren —
MemberRemoved/UnreachableMemberfür die Adresse des Hosts sagt dir, dass der ganze Node weg ist.
Siehe Death watch für die Per-Actor-Variante.
Serialisierung
Abschnitt betitelt „Serialisierung“Nachrichten, die die Leitung überqueren, müssen serialisierbar sein. Die SerializationExtension des Frameworks regelt das — JSON per Default, CBOR wenn konfiguriert.
{ kind: 'place', order: { items: ['book-1'], total: 19.99 }, replyTo: this.context.self, // ← Ref serialisiert als Pfad-String}Einfache Werte (Strings, Zahlen, Arrays, Plain Objects) serialisieren trivial. Dinge, die nicht überleben:
- Funktionen / Closures — können keine Prozessgrenze überqueren.
- Klasseninstanzen mit Methoden — Methoden gehen verloren; nur Datenfelder überleben.
Map/Set— JSON serialisiert sie als{}(keine Einträge). Nutze Plain Objects oder Arrays.- Symbols, BigInts (ohne Serializer-Registrierung).
Siehe Nachrichten für die Unveränderlichkeits- und Wire-Format-Konventionen.
Performance
Abschnitt betitelt „Performance“Grobe Zahlen:
- Lokales
tell(dasselbe Actor-System) — 50-200 ns. - Cluster-lokales
tell(Loopback-Transport) — sub-Millisekunde. - Cluster-
tellüber LAN — 0,5-2 ms für kleine Nachrichten. - Cluster-
tellüber WAN — durch die Netzwerk-RTT begrenzt.
Das Framework batched Envelopes opportunistisch — viele Tells in schneller Folge teilen sich TCP-Writes, wo möglich.
Wohin als Nächstes
Abschnitt betitelt „Wohin als Nächstes“- Cluster-Überblick — das größere Bild: wie sich Nodes finden, Gossip, Mitgliedschaft.
- Transports — TCP- und In-Memory-Implementierungen.
- Serialisierungs-Überblick — das Wire-Format für Cross-Node-Nachrichten.
- Nachrichten — die Konventionen, die Nachrichten serialisierbar machen.
- Death watch — erkennen, dass ein Remote-Actor gestoppt hat.
Die RemoteActorRef API-Referenz
deckt die Wire-Ref-Implementierung ab.