WebSocket Adapter
Table of Contents
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
- Appendix
Introduction
This document is a detailed technical document for WebSocket adapter, targeting real-time application developers, systematically explaining connection establishment process, message transmission protocol, connection state management, lifecycle management, heartbeat detection and disconnect reconnection strategy, message routing and broadcast mechanism, private channel management, connection pool and concurrent processing, memory optimization, error handling and exception recovery, performance monitoring and other key technical points. The document also provides usage guide, extension development suggestions and troubleshooting methods, helping developers quickly integrate and stably run WebSocket services.
Project Structure
WebSocket adapter is located in pkg/ws directory, adopts lightweight design, built around Gin middleware and gorilla/websocket library, provides thread-safe connection pool, broadcast and single-point/user-level message delivery capabilities, and built-in heartbeat keepalive mechanism.
Core Components
- Middleware and Connection Management: Responsible for identifying WebSocket requests, upgrading connections, generating client IDs, maintaining connection pool, starting message reading and heartbeat goroutines.
- Connection Pool: Map structure based on RWMutex, stores Client objects indexed by clientID.
- Message Routing and Broadcast: Provides convenient interfaces for global broadcast, single-point send, user-level broadcast, online count statistics, etc.
- Heartbeat Keepalive: Periodically sends ping messages, automatically removes connection on exception.
- Configuration Options: Supports custom CORS validation and heartbeat interval.
Architecture Overview
WebSocket adapter intercepts WebSocket handshake requests through Gin middleware, uses gorilla/websocket to complete upgrade, then starts two goroutines for each connection: message reading and heartbeat keepalive. Connection pool maintains all active connections with clientID as key, message sending interfaces implement broadcast and targeted delivery through traversing connection pool.
Detailed Component Analysis
Middleware and Connection Lifecycle
Request Identification
- Determines if it's a WebSocket handshake by checking Upgrade and Connection headers.
Connection Upgrade
- Uses upgrader to complete HTTP to WebSocket upgrade, returns 500 on failure.
Client Initialization
- Generates clientID (supports query parameter or header), extracts userID (supports query or header), wraps Client and adds to connection pool.
Lifecycle Startup
- Starts readMsg and startHeartbeat goroutines for each connection; readMsg removes connection on exception; startHeartbeat periodically sends ping, removes connection on failure.
Abort Subsequent Processing
- Interrupts current request chain after handshake completion, avoids other route processing.
Connection Pool and Concurrency
Data Structure
- clients is a map with RWMutex, key is clientID, value is Client pointer.
Concurrency Control
- In read-heavy scenarios, reading uses RLock, writing uses Lock; broadcast and send interfaces copy list first during traversal, reduce lock holding time.
Memory Optimization
- Pre-allocate slice capacity before traversal, reduce expansion; immediately remove connection on send failure, avoid zombie connections occupying memory.
Close Strategy
- removeClient calls Conn.Close(), and deletes map entry within lock.
Message Routing and Broadcast
Global Broadcast
- Traverses connection pool, WriteMessage one by one; collects failures and removes corresponding clients; returns aggregated error.
Single-Point Send
- Finds connection by clientID, removes on send failure; returns boolean or error.
User Broadcast
- Filters connection list by userID, sends one by one and handles failures.
JSON Serialization
- BroadcastJSON and SendJSON* interfaces perform JSON encoding internally, returns error on failure.
Text and Binary
- Provides Text and Binary two types of convenient interfaces.
Heartbeat and Disconnect Reconnection
Heartbeat Trigger
- startHeartbeat sends ping text message with heartbeatInterval period.
Exception Handling
- Heartbeat WriteMessage failure is considered connection unavailable, removes client and terminates goroutine.
Disconnect Reconnection
- Client side needs to implement reconnection logic; server does not actively initiate reconnection, only cleans up connection on heartbeat failure.
Configuration
- WithHeartbeatInterval supports custom heartbeat interval.
Private Channel Management
Private Channel
- Distinguishes users through Client.UserID field, SendToUser series interfaces implement user-level broadcast.
Channel Management
- Connection pool indexed by clientID, user dimension implements "private channel" semantics through userID filtering.
Extension Suggestions
- Can add channelID field in Client structure to achieve finer-grained channel isolation.
Configuration and Extension
Custom CORS
- WithCheckOrigin supports injecting custom validation function, meets production environment security requirements.
Heartbeat Interval
- WithHeartbeatInterval supports adjusting heartbeat period, balances keepalive and resource consumption.
Default Behavior
- Default allows any origin CORS, heartbeat interval is 10 seconds.
Error Handling and Exception Recovery
Upgrade Failed
- Logs and returns 500, avoids continuing processing.
Send Failed
- Logs failed client ID, immediately removes connection, prevents subsequent broadcast repeated failures.
Read Message Failed
- Logs exception and triggers connection removal, ensures connection pool consistency.
JSON Serialization Failed
- Returns wrapped error, convenient for upper layer handling.
Exception Recovery
- Achieves automatic cleanup through defer in goroutine and connection pool removal, avoids leakage.
Performance Monitoring
Online Count
- GetOnlineCount provides real-time statistics, can be used for frontend display and rate limiting strategy.
Periodic Broadcast
- Example demonstrates periodic broadcast of system statistics, can be extended to richer monitoring metrics.
Broadcast Performance
- Copies list first when traversing connection pool, reduces lock holding time; timely cleans up failed connections, avoids amplification effect.
Dependency Analysis
WebSocket adapter depends on Gin and gorilla/websocket, integrates into HTTP routing through middleware; application startup creates HTTP server and mounts routing through app.go, configuration provided by config.go.
Performance Considerations
- Connection Pool Scale: Current implementation is single map, suitable for small and medium scale concurrency; if higher throughput needed, can consider sharded lock or partitioned connection pool.
- Broadcast Strategy: Copy list when traversing connection pool, reduces lock contention; immediately removes failed connections, avoids subsequent repeated failures.
- Heartbeat Frequency: Reasonably set heartbeatInterval, too short increases CPU and bandwidth overhead, too long may cause gateway disconnect.
- Memory Occupancy: Timely clean up failed connections, avoids connection pool infinite growth; pay attention to JSON serialization overhead.
- Concurrency Model: Reading and heartbeat are in separate goroutines, avoids blocking; send interfaces are synchronous blocking, can change to asynchronous buffer queue according to business requirements.
[This section is general performance recommendations, no specific file source needed]
Troubleshooting Guide
Handshake Failed
- Check if request headers contain correct Upgrade and Connection; view middleware log output.
Send Failed
- Confirm if clientID is online; view failed client removal log; check client network status.
Heartbeat Failed
- Confirm heartbeatInterval setting is reasonable; check if client supports ping/pong; view connection removal log.
CORS Issues
- Use WithCheckOrigin to inject strict validation; ensure frontend request headers match configuration.
Performance Issues
- Monitor online count and broadcast latency; evaluate heartbeat frequency and message size; enable connection pool sharding if necessary.
Conclusion
This WebSocket adapter integrates Gin and gorilla/websocket with concise middleware pattern, provides thread-safe connection pool, complete broadcast and targeted delivery capabilities, built-in heartbeat keepalive and automatic cleanup mechanism. Through configuration options can flexibly customize CORS and heartbeat strategies. For high concurrency scenarios, recommend combining with sharded connection pool, asynchronous send queue and finer-grained channel management to further optimize performance and stability.
[This section is summary content, no specific file source needed]
Appendix
Usage Guide
- Mount middleware in Gin routing: r.Use(ws.Middleware()).
- Provide WebSocket route: r.GET("/ws", func(c *gin.Context) ).
- Send broadcast: ws.BroadcastText("Hello") / ws.BroadcastJSON(data).
- Query online count: ws.GetOnlineCount().
- Example reference: Example in file comments and periodic statistics broadcast.
Extension Development Suggestions
- Add channel management: Add channelID field in Client, implement multi-channel isolation.
- Asynchronous send: Introduce send queue and batch write, reduces lock contention.
- Connection pool sharding: Shard by clientID hash, reduces lock contention.
- Monitoring metrics: Expose Prometheus metrics, including online count, broadcast latency, heartbeat failure rate, etc.
- Disconnect reconnection: Implement exponential backoff reconnection strategy on client side, cooperate with server heartbeat keepalive.
[This section is extension suggestions, no specific file source needed]