Zum Inhalt

Skalieren mit Redis

Redis ist optional. Ein Dienst mit einem Connection-String redis teilt seinen Zustand darüber mit den anderen Instanzen; ohne ihn bleibt alles im Prozess und funktioniert für eine einzelne Instanz genauso.

Was Mit Redis Ohne
SignalR Backplane: Ein Ereignis erreicht die Verbindungen jeder Instanz die Verbindungen dieser Instanz
Anwesenheit ein Benutzer zählt einmal, egal welche Instanzen Verbindungen halten pro Instanz
Caches für Berechtigungen, Einstellungen, Features und Texte eine Änderung verwirft die Einträge sofort auf jeder Instanz andere Instanzen merken es innerhalb der Cache-Lebensdauer
Sitzungs-Stamps und Sitzungsänderungen gemeinsamer Stamp-Cache, Pub/Sub an jede Instanz (Clients und Sitzungen) eigene Instanz, die anderen innerhalb einer Minute
Topics nach Berechtigungsänderungen jede Instanz prüft ihre Verbindungen erneut (Realtime) eigene Instanz
Anmeldesitzungen der Web-App Sitzungsspeicher und Schlüsselring des Cookies in Redis: von den Instanzen geteilt, sie überstehen Neustarts Speicher und lokaler Schlüsselring
Verteilte Sperre Coworkee:DistributedLock:Provider = Redis (Ereignisse und Sperren) Postgres-Advisory-Locks

Aspire

Der AppHost gibt jedem Dienst, der Coworkee.Realtime referenziert (direkt oder über Coworkee.Identity), einen Redis-Container, ebenso der Web-App. Ein eigenes Redis oder keines:

builder.AddCoworkeeApp("shop", options =>
{
    // Produktion: ein vorhandenes Redis
    options.UseRedis(builder.AddConnectionString("redis"));

    // oder: eine Instanz pro Dienst, kein Container
    options.WithoutRedis();
});

coworkee new --redis false erzeugt den AppHost mit WithoutRedis(). Mit Redis (Standard) rufen die erzeugten Service-Defaults zusätzlich AddRedisClient("redis") aus Aspire.StackExchange.Redis auf: Health-Check und Traces für die Verbindung, die die Coworkee-Dienste mitbenutzen.

Wie es funktioniert

  • Caches. HybridCache hält die Caches mit Tags (Berechtigungen, Einstellungen, Features, Texte, gecachte Abfragen) in jeder Instanz, weil ein Entfernen per Tag eine zweite Ebene, die andere Instanzen lesen, nicht erreicht. Jedes Entfernen per Schlüssel oder Tag geht zusätzlich auf den Kanal coworkee:cache-invalidation; die anderen Instanzen verwerfen dieselben Einträge aus ihrem lokalen Cache.
  • Anwesenheit. Jede Instanz schreibt die Benutzer, für die sie Verbindungen hält, in einen eigenen Hash coworkee:presence:<instanz>, der nach 30 Sekunden abläuft, wenn die Instanz ihn nicht erneut schreibt (alle 10 Sekunden). Ein Benutzer, der sich verbindet, wird nur gemeldet, wenn keine andere Instanz ihn online hat; ein Benutzer, der geht, wird nur offline gemeldet, wenn keine andere Instanz noch eine Verbindung hält. Die Benutzer einer abgestürzten Instanz fallen mit ihrem Hash heraus.
  • Web-App. Die Data-Protection-Schlüssel des Sitzungs-Cookies liegen unter coworkee:bff:data-protection, sodass jede Instanz ein Cookie liest, das eine andere geschrieben hat.

Ein Redis, das nicht antwortet, ist nicht fatal: Die Dienste protokollieren eine Warnung und arbeiten mit dem, was sie lokal wissen.

Grenzen

Die Anwesenheitsabfrage liest den Hash jeder Instanz; für eine Handvoll Instanzen ist das in Ordnung. Benutzer einer abgestürzten Instanz verschwinden aus der Anwesenheitsliste, ein Offline-Ereignis wird für sie aber nicht gesendet.