feat(ws): implement WebSocket cluster mode with Redis Pub/Sub
Introduce a new WebSocket messaging architecture that supports both standalone and cluster modes. This allows for horizontal scaling of WebSocket servers by using Redis Pub/Sub to synchronize messages across multiple instances. Key changes: - Added `ws.MessagePublisher` interface to abstract message distribution. - Implemented `ws.Bus` to handle cluster-mode messaging via Redis. - Added `ws.OnlineTracker` to manage user online status across the cluster. - Refactored multiple services (Chat, Group, Push, Call, etc.) to use the new `MessagePublisher` instead of a concrete `ws.Hub`. - Added WebSocket configuration options (mode, instance ID, channel, TTL, heartbeat) to `config.yaml` and `config.go`. - Updated dependency injection with Wire to support the new publisher and Redis client. - Improved logging by replacing standard `log` with `zap` in several service components.
This commit is contained in:
@@ -46,8 +46,8 @@ var InfrastructureSet = wire.NewSet(
|
||||
ProvideBuiltinHooks,
|
||||
ProvideModerationHooks,
|
||||
|
||||
// WebSocket Hub
|
||||
ProvideWSHub,
|
||||
// WebSocket MessagePublisher
|
||||
ProvideWSMessagePublisher,
|
||||
|
||||
// 外部服务客户端
|
||||
ProvideOpenAIClient,
|
||||
@@ -163,9 +163,32 @@ func ProvideModerationHooks(
|
||||
return moderationHooks
|
||||
}
|
||||
|
||||
// ProvideWSHub 提供 WebSocket Hub
|
||||
func ProvideWSHub() *ws.Hub {
|
||||
return ws.NewHub()
|
||||
// ProvideWSMessagePublisher 提供 WebSocket 消息发布器
|
||||
// standalone 模式返回 *Hub,cluster 模式返回 *Bus(组合 Hub + Redis Pub/Sub)
|
||||
func ProvideWSMessagePublisher(cfg *config.Config, redisClient *redis.Client) ws.MessagePublisher {
|
||||
hub := ws.NewHub()
|
||||
|
||||
if cfg.WebSocket.Mode == "cluster" && redisClient != nil {
|
||||
bus := ws.NewBus(hub, redisClient.GetClient(), &ws.WSClusterConfig{
|
||||
InstanceID: cfg.WebSocket.Cluster.InstanceID,
|
||||
MsgChannel: cfg.WebSocket.Cluster.MsgChannel,
|
||||
OnlineTTL: cfg.WebSocket.Cluster.OnlineTTL,
|
||||
HeartbeatInterval: cfg.WebSocket.Cluster.HeartbeatInterval,
|
||||
})
|
||||
if err := bus.Start(); err != nil {
|
||||
zap.L().Error("Failed to start WebSocket Bus, falling back to standalone mode",
|
||||
zap.Error(err),
|
||||
)
|
||||
return hub
|
||||
}
|
||||
zap.L().Info("WebSocket running in cluster mode",
|
||||
zap.String("instance_id", bus.InstanceID()),
|
||||
)
|
||||
return bus
|
||||
}
|
||||
|
||||
zap.L().Info("WebSocket running in standalone mode")
|
||||
return hub
|
||||
}
|
||||
|
||||
// ProvideOpenAIClient 提供 OpenAI 客户端
|
||||
|
||||
Reference in New Issue
Block a user