Level 4: Real-time Event Notification System (WebSockets & Redis Pub/Sub)¶
Welcome to the final level! You are now building a distributed, real-time messaging system.
In real-world production setups, single-node web servers can't scale to millions of concurrent websocket connections. We need to share state across multiple server instances. To do this, we use a message broker like Redis Pub/Sub.
graph TD
ClientA["WebSocket Client A"] <--> Server1["Server Instance 1"]
ClientB["WebSocket Client B"] <--> Server2["Server Instance 2"]
Server1 <-->|"Pub/Sub"| Redis["Redis Message Broker"]
Server2 <-->|"Pub/Sub"| Redis
Architectural Requirements¶
- WebSocket Handler: Upgrade incoming HTTP requests to WebSocket connections.
- Hub (Broadcaster): Maintain a registry of active client connections. Use channels to:
- Register new clients.
- Unregister disconnected clients.
- Broadcast messages to all connected clients.
- Redis Pub/Sub Integration:
- Listen to a Redis channel for external events.
- When an event is received, publish it to the local Hub to broadcast it to all connected WebSocket clients.
- Docker Compose Setup:
- Run the Go application.
- Spin up a Redis container.
The Hub Pattern in Go¶
In Go, we don't use locks on global arrays to track connections. Instead, we use a central event-loop goroutine (the Hub) that handles registration and broadcasting through channels. This is called "sharing memory by communicating" (Go's concurrency philosophy).
type Hub struct {
clients map[*Client]bool
broadcast chan []byte
register chan *Client
unregister chan *Client
}
func (h *Hub) Run() {
for {
select {
case client := <-h.register:
h.clients[client] = true
case client := <-h.unregister:
if _, ok := h.clients[client]; ok {
delete(h.clients, client)
close(client.send)
}
case message := <-h.broadcast:
for client := range h.clients {
select {
case client.send <- message:
default:
close(client.send)
delete(h.clients, client)
}
}
}
}
}
Getting Started¶
- Look at hub.go to see the Hub and Client struct definitions.
- Look at hub_test.go which simulates clients and verifies message distribution.
- Run the tests:
- Implement the Hub event loop and connection handling.