Chuyển tới nội dung chính
Chưa có bản tiếng Việt
Trang này hiện chỉ có bằng tiếng Anh. Các bài trong mục Production patterns đã được dịch.

High Performance WebSocket Broker

Overview

High-performance WebSocket service for streaming events to end users in a Centralized Exchange (CEX) system — robust, scalable, and low-latency architecture.


1. Core Requirements​

Functional Requirements​

  • Dynamic integration with external event streams (e.g., Kafka, NATS, Redis Stream)
  • Routing logic per event stream (e.g., queue-to-WebSocket channel binding)
  • Mapping/transformation layer per stream (e.g., raw → client-specific format, aggregation, filtering)
  • Fault tolerance: if a server fails, clients can reconnect to another available server in the cluster

Non-Functional Requirements​

  • Massive Concurrency: 100K+ concurrent WebSocket connections
  • Low Latency: < 100ms end-to-end event delivery
  • Horizontal Scalability
  • Multi-region support (optional)

Incoming Event Stream Types​

  • Real-time trade events (trade stream)
  • Order book updates (depth stream)
  • Price ticker updates (ticker)
  • User-specific streams (authenticated via token)

2. Technology Stack​

LayerTech Choice
LanguageRust
WebSocket Servertokio, rust-libp2p, axum
Broker/QueueNATS, Kafka, or Redis Streams
AuthenticationJWT / OAuth2 (token-based over initial handshake) / API-KEY
OrchestrationKubernetes (with auto-scaling)
ObservabilityPrometheus + Grafana + Loki/ELK

3. Implementation Strategy​

A. WebSocket Gateway​

  • Written in Go or uWebSockets.js for high concurrency
  • Handle subscribe/unsubscribe messages
  • Authenticate with JWT
  • Maintain channel-to-client-list mapping
  • Push data from broker to clients using in-memory pub/sub

B. Event Broker​

  • Matching engine publishes events to Kafka/NATS per topic: trades.btc_usdt, depth.eth_usdt, ticker.global
  • Use partitions (Kafka) or topics (NATS) for high fanout performance

C. Data Channel Format​

{
"stream": "depth.btc_usdt",
"data": {
"asks": [["36200.5", "1.2"]],
"bids": [["36190.1", "1.1"]],
"timestamp": 1724548345123
}
}

4. Scalability & Resilience​

ConcernSolution
Scaling WSStateless WS servers with sticky sessions or centralized pub/sub
ResilienceRetry on publish failure, circuit breakers
BackpressureDrop slow clients, use bounded queues
Horizontal ScaleDeploy WS Gateway with Kubernetes HPA + custom autoscaler on CPU & connection count

5. Security​

  • WebSocket authentication during handshake:
  • Clients provide JWT
  • JWT is validated by Auth service
  • Message signing for sensitive topics (like orders)
  • WAF or Layer-7 firewall (AWS WAF, Cloudflare, etc.)

6. Observability​

Track:

  • Number of active connections
  • Events per second
  • Latency (matching engine → user)
  • Dropped events, client disconnects

Use:

  • Prometheus metrics in Go
  • Logs to Loki or ELK stack
  • Grafana dashboards

MVP Deliverables​

  • WebSocket Gateway with topic subscriptions
  • Kafka/NATS integration
  • Sample clients (web + CLI)
  • Dashboard for live metrics
  • Test with 10K–100K concurrent simulated clients using Artillery or k6

7. Acceptance Use Cases​

Use Case 1: WebSocket Handshake with Authorization​

Actors: Web Client / Mobile Client, WebSocket Gateway, Auth Service

Description: Clients initiate WebSocket connection with a JWT or API key.

Flow
  1. Client connects to /ws endpoint
  2. During the upgrade request, the client includes a JWT in headers or query param
  3. WebSocket Gateway validates the JWT with the Auth Service
  4. On success:
  • User info (userId, roles, allowedPairs) is extracted and cached
  • Connection is accepted
  1. On failure: return HTTP 401 and reject upgrade

Events: onConnectionOpen() → onAuthValidate(token) → onConnectionAccepted() / onConnectionRejected()


Use Case 2: Subscribe to Allowed Topics​

Actors: Authenticated Client, WebSocket Gateway

Description: After successful handshake, client sends a subscription request.

Flow

Example Topics: ticker.btc_usdt, depth.btc_usdt, orders.user123 (private)

  1. Client sends:
{"action": "subscribe", "streams": ["ticker.btc_usdt", "orders.user123"]}
  1. WebSocket Gateway validates topic access (e.g., user can only subscribe to orders.user123)
  2. Registers client to internal channel (e.g., Redis pub/sub or in-memory topic map)

Events: onSubscribeRequest(streams) → onTopicPermissionCheck() → onSubscriptionConfirmed()


Use Case 3: Receive Streamed Data from Kafka​

Actors: Kafka, WebSocket Gateway

Description: Internal services (e.g., Matching Engine) publish messages to Kafka. The Gateway consumes and routes them to subscribed clients.

Flow
  1. Matching Engine publishes message:
{
"stream": "ticker.btc_usdt",
"data": {"price": "36200.5", "volume": "1.25", "timestamp": 1724548381123}
}
  1. Kafka consumer inside WebSocket Gateway receives the message
  2. Gateway looks up clients subscribed to ticker.btc_usdt
  3. Message is broadcasted to all connected WebSocket clients of that topic

Events: onKafkaMessage(topic, message) → onMessageDispatch(topic → clients[])


Use Case 4: Unsubscribe from a Topic​

Actors: Authenticated Client

Description: Clients can unsubscribe from specific topics to save bandwidth.

Flow
  1. Client sends:
{"action": "unsubscribe", "streams": ["ticker.btc_usdt"]}
  1. Gateway removes client from internal routing list for that topic

Use Case 5: Backpressure & Dropping Slow Clients​

Actors: WebSocket Gateway

Description: If client cannot consume messages fast enough, drop it to avoid memory leaks.

Flow
  1. Gateway maintains a message queue per client (e.g., ring buffer or channel)
  2. If queue exceeds threshold or client write times out:
  • Send disconnect with reason
  • Close WebSocket

Use Case 6: Private Stream for Authenticated User​

Actors: Authenticated Client, Order Service

Description: Users receive their order updates through orders.user123 stream.

Flow
  1. Order Service publishes private order update to Kafka topic: orders.user123
  2. WebSocket Gateway reads this Kafka topic
  3. Routes message only to the client authenticated as user123

Use Case 7: Reconnect with Resume Support​

Actors: Authenticated Client, WebSocket Gateway

Description: If connection is lost, allow client to reconnect and resume from last known sequence.

Flow
  1. Client reconnects and sends:
{"action": "resume", "streams": ["depth.btc_usdt"], "lastSequence": 21253412}
  1. Gateway queries cache or buffer (e.g., Redis or local memory) for missed messages
  2. Sends missed updates, then resumes real-time stream

Summary Table​

Use CaseDescriptionKey Events
Handshake + AuthJWT-based connection initonAuthValidate
Subscribe TopicsSubscribe to market/private topicsonSubscribeRequest
Kafka to ClientsConsume Kafka & push to clientsonKafkaMessage
UnsubscribeStop receiving a streamonUnsubscribeRequest
BackpressureDrop or pause slow clientsonClientOverload
Private StreamsPer-user updatesonUserStreamPush
Resume SupportReconnect and resumeonResumeStream