Preskoči na sadržaj
nazad na projekte

// projekat ·

Real-time distribuirani chat sistem

Napravio sam chat da vidim šta puca kada jedan server postane više njih. Stack: Go, WebSocket, Redis, Docker.

Go / WebSocket / Redis Pub/Sub / Docker / React

Uloga: Lični projekat · Godina: 2024 - 2025 · Status: isporučeno

ukratko: Chat sistem napravljen da proučim šta puca kad WebSocket saobraćaj mora da živi na više servera. Goroutine-ovi drže konekcije, Redis Pub/Sub širi poruke između čvorova, a mali prilagođeni load balancer stoji ispred. Zanimljiv deo nije chat, nego ono što prestane da radi kad pređeš sa jednog čvora na dva.

Problem

Chat server na jednom čvoru drži svaku konekciju u memoriji i to radi. Dodaš drugi čvor i stanje se rasparča: korisnik na serveru A ne može do korisnika na serveru B, jer A nema pristup socket-ima servera B. Upravljanje konekcijama mora da se odvoji od distribucije poruka.

Ograničenja

  • Socket-i ne mogu da se sele. WebSocket je dugotrajna TCP konekcija vezana za jedan proces. Premeštanje znači prekid veze.
  • Memorija po čvoru je tesna. Nema teškog framework sloja između socket-a i logike chat-a.
  • Redosled i praćenje. Poruke moraju da stignu redom, a sistem mora da zna ko je gde povezan dok se čvorovi dodaju i uklanjaju.

Odluke

  • Go za servere. Goroutine-ovi drže neaktivne konekcije jeftinim i izbegavaju callback event loop-ove.
  • Redis Pub/Sub kao magistrala. Čvorovi ne sinhronizuju liste klijenata. Poruka koja stigne na server A objavljuje se na kanal, a server B je prima i upisuje svojim lokalnim klijentima.
  • Docker za topologiju, pa je prelazak sa jednog čvora na više ponovljiv lokalno.

Ishod

U testovima horizontalnog skaliranja svaki čvor je držao 500+ istovremenih konekcija, sa neaktivnim goroutine-ovima ispod 10 KB. Glavni kompromis je isporuka. Redis Pub/Sub je at-most-once: čvor koji se restartuje u trenutku objave nikad ne vidi tu poruku. Za proučavanje fan-out-a to sam prihvatio i izabrao eventual consistency umesto distribuiranog zaključavanja. Trajna isporuka bi značila prelazak na Redis Streams ili log sa offset-ima potrošača.