Zum Inhalt springen
Deutsch

HTTP-Endpunkte

Der Management-Server stellt einen kleinen Satz operativer Endpunkte bereit. Die meisten sind read-only (sicher fürs Monitoring zu exponieren); Admin-Endpunkte sind Opt-in.

Liveness — ist dieser Prozess fundamental gesund?

GET /health
→ 200 OK
{
"ok": true,
"checks": {
"actor-system-alive": { "ok": true }
}
}

503 mit { ok: false }, wenn ein Check fehlschlägt. Siehe Health Checks.

Readiness — sollte dieser Pod Traffic bekommen?

GET /ready
→ 200 OK
{
"ok": true,
"checks": {
"actor-system-alive": { "ok": true },
"cluster-up": { "ok": true }
}
}

Der cluster-up-Check schlägt fehl, bis SelfUp feuert. Eigene Checks tragen zur Response bei. 503, wenn einer fehlschlägt.

Verfügbar, wenn cluster an HttpManagement.start übergeben wurde.

GET /cluster/members
→ 200 OK
{
"selfAddress": "actor-ts://my-app@10.0.0.5:2552",
"leader": "actor-ts://my-app@10.0.0.5:2552",
"members": [
{
"address": "actor-ts://my-app@10.0.0.5:2552",
"status": "up",
"roles": ["compute"],
"uniqueAddress": { "address": "...", "uid": 1 }
},
...
]
}

Voller Membership-Snapshot. Nützlich für:

  • Manuelle Cluster-Zustand-Checks während Incidents.
  • Externe Dashboards, die den Cluster visualisieren.
  • Tests, die das Cluster-Joining verifizieren.
GET /cluster/leader
→ 200 OK
{ "leader": "actor-ts://my-app@10.0.0.5:2552" }

Nur die Adresse des Leaders. Nützlich zum Monitoring von Leader-Wechseln.

GET /cluster/shards?type=cart
→ 200 OK
{
"typeName": "cart",
"regions": [
{
"address": "actor-ts://my-app@10.0.0.5:2552",
"shards": [0, 1, 2, ..., 33]
},
{
"address": "actor-ts://my-app@10.0.0.6:2552",
"shards": [34, 35, ..., 66]
},
...
]
}

Zeigt die Shard-zu-Region-Allokation für einen sharded Typ. Nutze für:

  • Verifizieren gleichmäßiger Verteilung nach einem Rebalance.
  • Diagnostizieren heißer Regionen (eine Region mit zu vielen Shards).
  • Manuelle Rebalance-Trigger in der Entwicklung.

Opt-in via enableMetricsEndpoint: true.

GET /metrics
→ 200 OK
Content-Type: text/plain; version=0.0.4
# HELP actor_messages_processed_total ...
# TYPE actor_messages_processed_total counter
actor_messages_processed_total{class="Worker",path="..."} 12345
...

Prometheus-Textformat. Siehe Prometheus-Exporter.

Opt-in via enableLeaveEndpoint: true.

POST /cluster/leave
→ 200 OK
{ "status": "leaving" }

Löst einen Graceful Cluster-Leave aus. Der Node läuft durch leavingexitingremoved; Shards rebalancen weg; das Actor-System terminiert (konfigurierbar).

Nutze für:

  • Pod-Außerbetriebnahme vor einem Rolling Update.
  • Manuellen Node-Out während Incidents.

Hinter Authentifizierung gaten — jeder mit Portzugriff kann deinen Node drainen.

Opt-in via enableDownEndpoint: true.

POST /cluster/down
{ "address": "actor-ts://my-app@10.0.0.5:2552" }
→ 200 OK
{ "downed": "actor-ts://my-app@10.0.0.5:2552" }

Force-downt ein Remote-Mitglied per Adresse. Destruktiv — die Actor des Targets stoppen, seine Shards reallokieren woanders.

Nutze für:

  • Split-Brain-Recovery, wenn keine Downing-Strategie konfiguriert ist.
  • Entfernen von hängenden unreachable-Mitgliedern, die sich weigern, sich zu erholen.

Hochrisiko-Endpunkt — hinter Auth + Audit-Logs gaten.

import { managementRoutes, path, get, concat, completeJson } from 'actor-ts';
const baseRoutes = managementRoutes(system, cluster).routes;
const customRoutes = concat(
baseRoutes,
path('admin',
get(async () => completeJson(200, { appVersion: '1.2.3' })),
),
);
await http.newServerAt(host, port).bind(customRoutes);

managementRoutes(system, cluster, opts) gibt die Basis-Routen zurück; kombiniere mit eigenen via concat. Nützlich, um app-spezifische Admin-Endpunkte neben dem Standard-Satz hinzuzufügen.

Alle Endpunkte geben standardmäßig JSON zurück, mit einer Ausnahme: /metrics gibt text/plain für Prometheus zurück.

Fehler sind strukturiert:

{
"error": "Missing query parameter: type",
"status": 400
}

Status-Codes folgen HTTP-Konventionen: 200 für Erfolg, 4xx für Client-Fehler, 5xx für Server-Fehler.

Die privilegierten Endpunkte (/cluster/down, /cluster/leave, /cluster/members, /cluster/shards, /metrics) akzeptieren standardmäßig anonyme Requests. Das ist nur sicher, wenn der Management-Port auf einem netzwerkisolierten Bind sitzt (separater Service, anderer Port, 127.0.0.1-only) oder hinter einem Reverse-Proxy, der die Auth für dich übernimmt.

Für Produktions-Deployments, die Management-Endpunkte einem breiteren Netz exponieren, hänge die mitgelieferten Middlewares über managementRoutes(system, cluster, { auth, ipAllowlist }) an:

import {
BearerTokenAuth,
IpAllowlist,
managementRoutes,
} from 'actor-ts';
const { routes } = managementRoutes(system, cluster, {
enableLeaveEndpoint: true,
enableDownEndpoint: true,
enableMetricsEndpoint: true,
// Shared-Secret-Bearer-Token (Rotation über mehrere Einträge).
auth: BearerTokenAuth({
tokens: [process.env.MGMT_TOKEN!],
realm: 'my-app-mgmt',
}),
// Netzwerk-Level-Fence — nur Requests aus diesen CIDRs
// erreichen die Anwendung überhaupt.
ipAllowlist: IpAllowlist({
allow: ['10.0.0.0/8', '127.0.0.1/32'],
// Operatoren hinter einem trusted Reverse-Proxy: gib einen
// Custom-Extractor mit, der x-forwarded-for liest (der
// Default liest die Socket-Peer und ignoriert
// Forwarded-Header).
// getClientIp: (req) => req.headers['x-forwarded-for']?.split(',')[0]?.trim(),
}),
});

Policy-Trennung:

  • auth wrappt die privilegierte Teilmenge (/cluster/*, /metrics). /health und /ready bleiben anonym — Kubernetes- Liveness-/Readiness-Probes können nicht so leicht einen Authorization-Header mitschicken. Setze authProtectHealth: true, wenn dein Deployment garantiert, dass die Probes Credentials präsentieren können.
  • ipAllowlist wrappt JEDEN Endpunkt inklusive /health und /ready. Netzwerk-Level-Isolation ist unabhängig davon, wer authentifiziert ist.

Fehlermodi:

  • Fehlender / falscher Authorization-Header → 401 Unauthorized mit WWW-Authenticate: Bearer realm="...".
  • Client-IP außerhalb der Allowlist (oder unauflösbar) → 403 Forbidden.

Die Middlewares sind general-purpose — du kannst sie auch außerhalb des Management-Subtrees über den withMiddleware(mw, route)-Builder einsetzen.