即时通讯在线客服系统源码-使用Golang Gin 和 Redis实现分布式webocket

使用 Go 实现一个基于 Gin 框架和 Redis 的分布式 WebSocket 系统需要以下几个步骤:

实现架构

  1. Gin 处理 HTTP/WebSocket 请求
    • Gin 用于启动 HTTP 服务并处理 WebSocket 请求。
  2. Redis Pub/Sub
    • Redis 用于跨节点消息分发。
  3. WebSocket 连接管理
    • 在服务内维护 WebSocket 连接池。

代码实现

以下是一个简单的示例代码:

1. 安装依赖

使用 go mod 初始化项目并安装依赖:

复制代码
go mod init websocket-example
go get -u github.com/gin-gonic/gin
go get -u github.com/go-redis/redis/v8
  1. 服务端代码

    package main

    import (
    "context"
    "fmt"
    "log"
    "net/http"
    "sync"

    复制代码
     "github.com/gin-gonic/gin"
     "github.com/go-redis/redis/v8"
     "github.com/gorilla/websocket"

    )

    // Redis context and client
    var ctx = context.Background()
    var redisClient = redis.NewClient(&redis.Options{
    Addr: "localhost:6379", // Redis 地址
    })

    // WebSocket upgrader
    var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
    return true // 允许所有来源连接
    },
    }

    // Connection pool to manage active WebSocket connections
    var connections = make(map[string]*websocket.Conn)
    var connLock sync.Mutex

    func main() {
    r := gin.Default()

    复制代码
     // WebSocket endpoint
     r.GET("/ws/:channel", func(c *gin.Context) {
         channel := c.Param("channel")
    
         // 升级为 WebSocket
         conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
         if err != nil {
             log.Println("Upgrade error:", err)
             return
         }
         defer conn.Close()
    
         // 将连接加入连接池
         connLock.Lock()
         connections[channel] = conn
         connLock.Unlock()
    
         // 启动 Redis 订阅
         go subscribeToRedis(channel, conn)
    
         // 监听客户端发送的消息
         for {
             _, message, err := conn.ReadMessage()
             if err != nil {
                 log.Println("Read error:", err)
                 break
             }
    
             // 发布消息到 Redis
             err = redisClient.Publish(ctx, channel, string(message)).Err()
             if err != nil {
                 log.Println("Redis publish error:", err)
             }
         }
    
         // 连接断开时,从连接池中移除
         connLock.Lock()
         delete(connections, channel)
         connLock.Unlock()
     })
    
     // 启动服务器
     r.Run(":8080")

    }

    // Subscribe to Redis channel
    func subscribeToRedis(channel string, conn *websocket.Conn) {
    sub := redisClient.Subscribe(ctx, channel)
    defer sub.Close()

    复制代码
     ch := sub.Channel()
     for msg := range ch {
         connLock.Lock()
         err := conn.WriteMessage(websocket.TextMessage, []byte(msg.Payload))
         connLock.Unlock()
    
         if err != nil {
             log.Println("Write error:", err)
             break
         }
     }

    }

代码说明

  1. Gin 路由GET /ws/:channel 用于处理 WebSocket 请求,channel 参数用于标识消息主题(类似于聊天室或订阅主题)。

  2. Redis Pub/Sub

    • Publish:当 WebSocket 客户端发送消息时,服务端将消息发布到 Redis 的指定频道。
    • Subscribe:服务端订阅 Redis 频道,当有新消息时将其发送到 WebSocket 客户端。
  3. WebSocket 连接管理 : 使用 map[string]*websocket.Conn 存储活动连接,方便在断开时清理。

  4. 并发安全

    使用 sync.Mutex 确保对共享连接池的并发访问是安全的。


测试

    1. 启动 Redis 服务器:

    redis-server

  1. 启动 WebSocket 服务:

    复制代码
    go run main.go
  2. 使用 WebSocket 客户端(如 wscat 或网页工具)测试:

    • 连接服务:

      复制代码
      wscat -c ws://localhost:8080/ws/mychannel
    • 发送消息:
      在一个客户端发送消息,另一个客户端会收到通过 Redis 分发的消息。


优化方向

    1. 连接池优化 :可以使用库如 gorilla/websocket 提供的连接管理工具。
    2. 日志记录:增加更详细的日志以调试问题。
    3. Redis 配置:生产环境中使用 Redis 集群和持久化机制。
    4. 扩展:通过负载均衡器(如 Nginx 或 Traefik)支持多实例部署。

感兴趣的 contact me wechat : llike620

相关推荐
云泽8087 分钟前
从零吃透 C++ 异常:抛出捕获、栈展开、异常重抛与编码规范详解
开发语言·c++·代码规范
灯澜忆梦10 分钟前
GO---可见性规则
开发语言·golang
逝水无殇23 分钟前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
六bring个六1 小时前
open Harmony中分布式软总线的学习任务清单
分布式·学习·c/c++·open harmony
这是个栗子1 小时前
前端开发中的常用工具函数(八)
开发语言·前端·javascript
凤凰院凶涛QAQ1 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
wuqingshun3141592 小时前
说一下 Kafka 中关于事务消息的实现?
分布式·kafka
研☆香2 小时前
为什么变量声明在赋值前也能使用?—— 深入理解 JavaScript 变量提升与作用域
开发语言·前端·javascript
右耳朵猫AI2 小时前
PHP周刊2026W28 | 安全更新、Laravel 13.18、Twig 3.28
开发语言·php·laravel
second602 小时前
第一部分:快速上手 —— 建立 C++ 基本语法与编程范式
开发语言·c++