Worker-Mesh
JavaScript ist pro Actor-System Single-Threaded. Für
Parallelität innerhalb eines einzelnen OS-Prozesses lässt das
Worker-Mesh des Frameworks mehrere ActorSystems laufen —
eines pro Worker-Thread — die alle am selben Cluster über einen
MessageChannel-Transport teilnehmen.
Jeder ist aus Sicht des Clusters ein separater Cluster-Node — Gossip + Mitgliedschaft + Sharding gelten alle. Die Kommunikation zwischen ihnen läuft über In-Process-MessageChannel (keine Serialisierung zu Bytes, kein TCP).
Wann verwenden
Abschnitt betitelt „Wann verwenden“Zwei Hauptszenarien:
- CPU-gebundene Parallelität in einem Prozess — actor-ts ist pro System Single-Threaded; Multi-Threading braucht mehrere Systeme. Worker-Mesh verteilt sie.
- Isolation innerhalb eines Prozesses — ein “Worker”, der ausfällt, reißt das Hauptsystem nicht mit.
Für Multi-Process-Parallelität (separate OS-Prozesse) nutze den regulären Cluster + TCP-Transport. Worker-Mesh ist speziell für den In-Process-Fall.
// main.ts — Hauptthreadimport { Worker } from 'node:worker_threads';import { ActorSystem, Cluster, MessageChannelTransport } from 'actor-ts';
const channel = new MessageChannel();
const w1 = new Worker('./worker.js', { workerData: { mainPort: channel.port2 }, transferList: [channel.port2],});
const transport = new MessageChannelTransport({ self: 'main', ports: [channel.port1],});
const system = ActorSystem.create('main');await Cluster.join(system, { host: 'main', port: 0, seeds: ['main'], transport,});
// worker.js — läuft im Worker-Threadimport { parentPort, workerData } from 'node:worker_threads';import { ActorSystem, Cluster, MessageChannelTransport } from 'actor-ts';
const transport = new MessageChannelTransport({ self: 'w1', ports: [workerData.mainPort],});
const system = ActorSystem.create('w1');await Cluster.join(system, { host: 'w1', port: 0, seeds: ['main'], transport,});
// Ab hier ist w1 einfach ein weiterer Cluster-NodeDie Mesh-Form
Abschnitt betitelt „Die Mesh-Form“Für mehrere Worker braucht jedes Paar einen MessageChannel. Ein voll vermaschtes Mesh mit 4 Workern braucht 6 Channels (binomial(4,2)).
Der MessageChannelTransport des Frameworks akzeptiert ein
Array von Ports:
new MessageChannelTransport({ self: 'main', ports: [ portToW1, portToW2, portToW3, ],});Jeder Port zielt auf einen Peer.
Für größere Meshes ist die Stern-Topologie (alle reden mit main; main leitet weiter) einfacher — nur N-1 Channels nötig. Aber das macht main zum Flaschenhals.
Wie es sich vom TCP-Cluster unterscheidet
Abschnitt betitelt „Wie es sich vom TCP-Cluster unterscheidet“TCP-Transport: MessageChannelTransport:- Sockets, Framing - postMessage zwischen Threads- Serialisierte Bytes - Structured Cloning (kein JSON)- Netzwerklatenz - Sub-Mikrosekunde- Cross-Host - Nur derselbe ProzessNachrichten zwischen Worker-Systemen gehen durch Structured Clone — schneller als JSON.stringify + parse und erhalten mehr Typen (Map, Set, Date etc.).
Anwendungsfälle
Abschnitt betitelt „Anwendungsfälle“Sharding über Cores
Abschnitt betitelt „Sharding über Cores“// 4-Worker-Mesh; Sharding verteilt Entities über sie:sharding.start({ typeName: 'order', entityProps: ..., extractEntityId: (msg) => msg.id, numShards: 16,});Der Koordinator (auf main) allokiert Shards auf die 4 Worker. CPU-gebundene Entity-Arbeit parallelisiert über Cores.
Per-Worker-Isolation
Abschnitt betitelt „Per-Worker-Isolation“// Worker, der GPU-gebundene Jobs handhabt:system.spawn(Props.create(() => new GpuJobActor()), 'gpu-jobs');
// Abstürze in diesem Worker bleiben isoliert von main + anderen WorkernEin abstürzender Worker reißt das Hauptsystem nicht mit — separate Event-Loops.
Wann NICHT verwenden
Abschnitt betitelt „Wann NICHT verwenden“Wohin als Nächstes
Abschnitt betitelt „Wohin als Nächstes“- Cluster-Überblick — das Cluster-Modell, an dem das Worker-Mesh teilnimmt.
- Transports — die Transport-Schnittstelle, die MessageChannelTransport implementiert.
- Sharding — der Hauptnutzer der Mesh-Parallelität.