Preise

Architektur im Überblick

Quelldateien

Diese Seite wurde aus den folgenden Quelldateien erstellt:

Das gochat-Projekt ist eine in Go implementierte Chat-Anwendung mit Microservice-Architektur, die WebSocket- und TCP-Verbindungen für Echtzeitkommunikation unterstützt. Das System ist modular aufgebaut und ermöglicht horizontale Skalierung durch Entkopplung der einzelnen Komponenten.

Modulare Architektur und Komponenten

Das System besteht aus fünf eigenständigen Modulen, die unabhängig voneinander gestartet und skaliert werden können. Die Modul-Auswahl erfolgt über Kommandozeilenparameter beim Start der Anwendung.

正在加载图表渲染器...

Modul-Struktur und Einstiegspunkt

Der Haupteinstiegspunkt in main.go:21-48 definiert sechs Betriebsmodi:

ModulStart-ParameterPrimäre Verantwortlichkeit
LogiclogicAuthentifizierung, Benutzerverwaltung, Sitzungsmanagement
Connect WebSocketconnect_websocketWebSocket-Verbindungen, Keep-Alive, Message-Framing
Connect TCPconnect_tcpTCP-Long-Connections, binäres Protokoll
TasktaskAsynchrone Aufgaben, Redis Pub/Sub, Push-Benachrichtigungen
APIapiRESTful API für externe Integration
SitesiteWeb-Frontend-Server

Die Modul-Auswahl erfolgt über ein Switch-Statement, das den entsprechenden Modul-Initialisierer aufruft. Nach dem Start wartet das System auf Betriebssystem-Signale (SIGHUP, SIGINT, SIGTERM, SIGQUIT) für ein kontrolliertes Herunterfahren.

Abhängigkeitsmanagement

Die go.mod:1-22 Datei definiert die Kernabhängigkeiten:

  • gin-gonic/gin v1.7.7: HTTP-Framework für API und Site
  • gorilla/websocket v1.5.0: WebSocket-Implementierung
  • go-redis/redis v6.15.9: Redis-Client für Messaging und Caching
  • smallnest/rpcx v1.7.4: RPC-Framework für interne Kommunikation
  • rpcxio/rpcx-etcd v0.1.0: Service Discovery über etcd
  • jinzhu/gorm v1.9.16: ORM für Datenbankoperationen
  • spf13/viper v1.11.0: Konfigurationsmanagement

RPC-Kommunikation und Protokolldefinitionen

Die Kommunikation zwischen Logic- und Connect-Servern erfolgt über RPC mit explizit definierten Request/Response-Strukturen. Diese Entkopplung ermöglicht unabhängige Skalierung der Verbindungsschicht.

Authentifizierungs-Protokoll

Das Authentifizierungssystem definiert mehrere Operationen in proto/logic.go:7-56:

go
1type LoginRequest struct {
2    Name     string
3    Password string
4}
5
6type LoginResponse struct {
7    Code      int
8    AuthToken string
9}
10
11type CheckAuthRequest struct {
12    AuthToken string
13}
14
15type CheckAuthResponse struct {
16    Code     int
17    UserId   int
18    UserName string
19}

Der Authentifizierungsfluss umfasst:

  1. Login: Validierung von Name/Passwort, Generierung eines AuthToken
  2. Token-Validierung: Überprüfung des AuthToken bei jeder Operation
  3. Logout: Invalidierung des AuthToken

Benutzer- und Verbindungsmanagement

Die ConnectRequest-Struktur verknüpft eine WebSocket/TCP-Verbindung mit einem authentifizierten Benutzer. Die DisconnectRequest behandelt Verbindungsabbau und bereinigt Benutzer-spezifische Ressourcen.

Push-Nachrichten-Formate

Die Connect-Komponente definiert Nachrichtenformate in proto/connect.go:7-28 für Echtzeit-Push:

go
1type Msg struct {
2    Ver       int    `json:"ver"`  // Protocol version
3    Operation int    `json:"op"`   // Operation code
4    SeqId     string `json:"seq"`  // Client sequence ID
5    Body      []byte `json:"body"` // Binary payload
6}
7
8type PushMsgRequest struct {
9    UserId int
10    Msg    Msg
11}
12
13type PushRoomMsgRequest struct {
14    RoomId int
15    Msg    Msg
16}

Die Msg-Struktur unterstützt:

  • Ver: Protokoll-Versionierung für Abwärtskompatibilität
  • Operation: Operationscode (z.B. 1=Ping, 2=Pong, 3=Message)
  • SeqId: Korrelation von Request/Response auf Client-Seite
  • Body: Binäre Nutzdaten für effiziente Übertragung

Task-Verarbeitung und Redis-Messaging

Die Task-Komponente fungiert als Message-Broker zwischen Logic und Connect, implementiert über Redis Pub/Sub für lose Kopplung und horizontale Skalierbarkeit.

Redis-Nachrichtenstrukturen

Die proto/task.go:7-33 definiert die Serialisierungsformate:

go
1type RedisMsg struct {
2    Op           int               `json:"op"`
3    ServerId     string            `json:"serverId,omitempty"`
4    RoomId       int               `json:"roomId,omitempty"`
5    UserId       int               `json:"userId,omitempty"`
6    Msg          []byte            `json:"msg"`
7    Count        int               `json:"count"`
8    RoomUserInfo map[string]string `json:"roomUserInfo"`
9}
10
11type RedisRoomCountMsg struct {
12    Count int `json:"count,omitempty"`
13    Op    int `json:"op"`
14}

Nachrichtenfluss-Architektur

正在加载图表渲染器...

Operations-Codes

Das System verwendet numerische Operations-Codes für verschiedene Nachrichtentypen:

Op-CodeBedeutungRichtung
1PingClient → Server
2PongServer → Client
3Einzel-NachrichtBidirektional
4Raum-NachrichtServer → Client
5Raum-BeitrittClient → Server
6Benutzer-ListeServer → Client

Raum-Management

Die RedisRoomInfo-Struktur verwaltet Raum-Metadaten:

  • RoomId: Eindeutige Raum-Identifikation
  • Count: Aktuelle Anzahl der Teilnehmer
  • RoomUserInfo: Map von Benutzer-ID zu Benutzer-Name

Architektur-Diagramme und Systemübersicht

Die visuelle Dokumentation in architecture/gochat.png:168-2330 zeigt die Gesamtarchitektur mit allen Komponenten und deren Verbindungen.

Service Discovery

Das architecture/gochat_discovery.png:461-3186 Diagramm illustriert die Service-Registrierung:

  1. Registrierung: Jeder Server registriert sich bei Start bei etcd
  2. Heartbeat: Periodische Health-Checks über etcd Lease
  3. Discovery: Clients und andere Services finden verfügbare Instanzen
  4. Load-Balancing: RPCX führt Client-seitiges Load-Balancing durch

Timing und Nachrichtenfluss

Das architecture/timing.png:548-1754 Diagramm zeigt zeitliche Abläufe:

  • Verbindungs-Timeout: 60 Sekunden Inaktivität vor Disconnect
  • Heartbeat-Intervall: 30 Sekunden zwischen Ping/Pong
  • RPC-Timeout: 5 Sekunden für synchrone Aufrufe
  • Redis-Publish: Asynchron mit Bestätigung

Kern-Design-Entscheidungen

1. Microservice-Architektur mit separaten Prozessen

Entscheidung: Jedes Modul läuft als eigenständiger Prozess, kommuniziert über RPC und Redis.

Begründung:

  • Unabhängige Skalierung: Connect-Server können basierend auf Verbindungszahl skaliert werden, Logic-Server basierend auf CPU-Last
  • Fehlertoleranz: Ausfall eines Connect-Servers betrifft nur dessen Verbindungen
  • Technologie-Flexibilität: Module können in unterschiedlichen Sprachen implementiert werden

Nachteil: Erhöhte Betriebskomplexität durch Service Discovery und verteiltes Tracing.

2. Redis als Message Broker

Entscheidung: Verwendung von Redis Pub/Sub statt dediziertem Message Broker (Kafka, RabbitMQ).

Begründung:

  • Geringe Latenz: Sub-Millisekunden für Publish-Operationen
  • Einfache Operation: Kein separater Message-Broker-Cluster erforderlich
  • Ausreichend für Chat-Anwendung: Keine persistente Nachrichtenspeicherung nötig

Einschränkung: Keine Nachrichtenpersistenz bei Server-Ausfall; Offline-Nachrichten müssen separat behandelt werden.

3. RPCX für interne Kommunikation

Entscheidung: RPCX statt gRPC für Service-to-Service-Kommunikation.

Begründung:

  • Integrierte Service Discovery: Native etcd-Integration
  • Load-Balancing: Client-seitiges Load-Balancing ohne zusätzlichen Proxy
  • Codec-Flexibilität: Unterstützung für JSON, Protobuf, MessagePack

Trade-off: Geringere Verbreitung als gRPC, weniger Tooling-Unterstützung.

4. Dual-Protokoll-Unterstützung

Entscheidung: Parallele Unterstützung für WebSocket und TCP.

Begründung:

  • WebSocket: Browser-Kompatibilität, HTTP-Fallback
  • TCP: Höhere Performance für native Clients, geringerer Overhead

Implementierung: Gemeinsame Codebasis in Connect-Modul mit separaten Listenern.

5. Zustandslose Logic-Server

Entscheidung: Logic-Server speichern keine Verbindungszustände.

Begründung:

  • Horizontale Skalierbarkeit: Jeder Logic-Server kann jede Anfrage bearbeiten
  • Einfache Load-Balancing: Round-Robin ohne Sticky Sessions
  • Ausfallsicherheit: Kein Zustandsverlust bei Server-Restart

Konsequenz: Verbindungs-Zustände werden in Redis und Connect-Servern gehalten.

Technologie-Stack und Abhängigkeiten

TechnologieVersionVerwendungszweckBegründung
Go1.18LaufzeitumgebungPerformance, Concurrency, statische Binaries
gin-gonic/gin1.7.7HTTP-FrameworkPerformance, Middleware-Ökosystem
gorilla/websocket1.5.0WebSocketStabil, weit verbreitet, vollständige RFC-Implementierung
go-redis/redis6.15.9Redis-ClientConnection-Pooling, Pub/Sub-Unterstützung
smallnest/rpcx1.7.4RPC-FrameworkService Discovery, Load-Balancing, Multiple Codecs
rpcxio/rpcx-etcd0.1.0Service Discoveryetcd-Integration für RPCX
jinzhu/gorm1.9.16ORMAuto-Migration, Association-Handling
spf13/viper1.11.0KonfigurationMulti-Format, Environment-Variablen, Hot-Reload
bwmarrin/snowflake0.3.0ID-GenerierungVerteilte, sortierbare IDs
sirupsen/logrus1.8.1LoggingStrukturiertes Logging, Hooks

Modul-Abhängigkeitsanalyse

正在加载图表渲染器...

Abhängigkeitsrichtungen

  1. Abwärtskompatibilität: Proto-Dateien haben keine Abhängigkeiten und definieren stabile Schnittstellen
  2. Schichten-Trennung: Präsentationsschicht hängt von Geschäftslogik ab, nicht umgekehrt
  3. Infrastruktur-Isolation: Infrastruktur-Komponenten sind durch Interfaces abstrahiert

Konfiguration und Deployment

Build-Prozess

Der Makefile:1-4 definiert den Docker-Build:

makefile
1build:
2    cd ./docker && docker build -t lockgit/gochat:${TAG} .

Der Build unterstützt benutzerdefinierte Tags für Versionierung und Architecture-spezifische Images (insbesondere für M1/M2 Macs).

Start-Up-Sequenz

Die empfohlene Start-Reihenfolge der Module:

  1. Infrastruktur: etcd, Redis, MySQL starten
  2. Logic: Business-Logik-Server initialisieren
  3. Task: Task-Verarbeitung starten
  4. Connect: Verbindungsserver starten (WebSocket und TCP)
  5. API/Site: Externe Schnittstellen aktivieren

Konfigurationsquellen

Viper unterstützt multiple Konfigurationsquellen mit Priorität:

  1. Kommandozeilen-Flags (höchste Priorität)
  2. Environment-Variablen
  3. Konfigurationsdatei (YAML/JSON/TOML)
  4. Standardwerte (niedrigste Priorität)

Fehlerbehandlung und Resilienz

Verbindungs-Fehler

  • Reconnect-Logik: Exponential-Backoff bei Verbindungsverlust
  • Circuit Breaker: Verhinderung von Kaskaden-Ausfällen bei RPC-Aufrufen
  • Graceful Degradation: Fallback auf Polling bei WebSocket-Fehlern

RPC-Timeouts

Das System implementiert Timeouts auf mehreren Ebenen:

  • Connection-Timeout: 5 Sekunden für RPC-Verbindungsaufbau
  • Request-Timeout: 10 Sekunden für RPC-Aufrufe
  • Idle-Timeout: 60 Sekunden für inaktive Verbindungen

Redis-Ausfall

Bei Redis-Unerreichbarkeit:

  • Task-Server: Nachrichten werden verworfen (Fire-and-Forget)
  • Logic-Server: Fallback auf lokale Caches
  • Connect-Server: Lokale Nachrichtenzustellung innerhalb desselben Servers