1 Star 0 Fork 0

niann/go-chat

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

基于 Go 语言开发的一套支持私聊与群聊的即时通讯系统,采用 RabbitMQ 进行消息异步处理,使用 WebSocket 实现消息实时推送,具备用户登录、好友系统、群组管理、消息存储与离线推送等功能,支持高并发和水平扩展。

主要功能:

用户注册 / 登录、鉴权与会话管理(基于JWT) 私聊与群聊功能,支持文本、表情、图片等类型的消息 WebSocket 实时通信,心跳检测与连接断线重连机制 消息持久化与离线消息存储,历史消息查询接口 群组创建、成员管理、群公告、群消息同步等功能 使用 RabbitMQ + Topic Exchange 进行消息路由与分发,解耦发送与处理逻辑 Redis 实现用户在线状态记录与消息缓存 接入 Prometheus + Grafana 实现服务监控,支持多实例部署与负载均衡

架构设计

已生成图片

功能

私聊

创建一个用户单独的队列,每个请求都发送到这个队列

群聊

使用广播交换机Fanout Exchange / Direct/Topic Exchange

  • 写扩散
  • 读扩散

群聊与私聊实现方案


1. 系统架构概述

  • 前端:通过 WebSocket 建立与服务器的长连接,实时发送和接收消息。
  • 后端
    • 使用 Go 语言和 Gin 框架处理 HTTP/WebSocket 连接。
    • 使用 RabbitMQ 作为消息中间件,负责消息的发布与订阅、路由转发。
  • 消息队列
    • 交换机采用 Topic Exchange,根据 routing key 动态路由消息。
    • 每个用户拥有专属队列,负责接收发给自己的私聊消息及其所加入群聊的群消息。

2. 消息模型

json复制编辑{
  "message": "消息内容",
  "to": "接收者ID或群ID",
  "type": "消息类型,0-私聊,1-群聊",
  "from": "发送者ID",
  "group_id": 1, 
  "createTime": "2025-06-18T13:24:00Z"
}
  • type=0 表示私聊,消息通过私聊 routing key 路由(格式如 private.id.{userId}
  • type=1 表示群聊,消息通过群聊 routing key 路由(格式如 group.id.{groupId}

3. RabbitMQ 设计

3.1 交换机

  • 统一使用一个 Topic 交换机,比如 message.topic
  • 交换机持久化(durable=true),确保服务器重启消息不过期

3.2 队列

  • 每个用户对应一个独立队列(如 queue.user.{userId}
  • 队列绑定多个 routing key,接收私聊和加入群的消息

3.3 Routing Key 设计

用途 格式 说明
私聊 private.id.{userId} 只发给指定用户
群聊 group.id.{groupId} 群内所有成员对应队列绑定此key

4. 消息路由与订阅流程

4.1 用户私聊订阅

  • 用户队列绑定对应私聊 routing key 例如用户 100 的队列绑定 private.id.100

4.2 用户群聊订阅

  • 用户加入群聊时,队列动态绑定群聊 routing key 例如群 10,用户 100 加入,则绑定 group.id.10
  • 用户退出群聊时,解绑对应 routing key

5. 动态绑定和解绑 Routing Key 示例

go复制编辑// 绑定 routing key(加入群聊)
func BindRoutingKey(ch *amqp.Channel, queueName, exchangeName, routingKey string) error {
    return ch.QueueBind(queueName, routingKey, exchangeName, false, nil)
}

// 解绑 routing key(退出群聊)
func UnbindRoutingKey(ch *amqp.Channel, queueName, exchangeName, routingKey string) error {
    return ch.QueueUnbind(queueName, routingKey, exchangeName, nil)
}

6. WebSocket 与消息消费

go复制编辑r.GET("/ws", func(c *gin.Context) {
    // WebSocket 升级
    upgrader := websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
    conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    // 假设从请求参数或认证中获取用户ID
    userId := c.Query("user_id")
    queueName := "queue.user." + userId
    exchangeName := "message.topic"

    ch, _ := rabbitMQConn.Channel()
    defer ch.Close()

    // 订阅用户专属队列,消费消息推送到 WebSocket
    go func() {
        msgs, _ := ch.Consume(queueName, "", true, false, false, false, nil)
        for d := range msgs {
            err := conn.WriteMessage(websocket.TextMessage, d.Body)
            if err != nil {
                break
            }
        }
    }()

    // 读取客户端消息并发布到交换机
    for {
        _, msg, err := conn.ReadMessage()
        if err != nil {
            break
        }
        // 解析消息,确定 routing key
        var payload MessagePayload
        json.Unmarshal(msg, &payload)

        var routingKey string
        if payload.Type == "0" { // 私聊
            routingKey = "private.id." + payload.To
        } else if payload.Type == "1" { // 群聊
            routingKey = "group.id." + strconv.Itoa(payload.GroupId)
        }

        ch.Publish(exchangeName, routingKey, false, false, amqp.Publishing{
            ContentType: "application/json",
            Body:        msg,
        })
    }
})

7. 总结

功能 说明
私聊 交换机通过 routing key private.id.{userId} 路由私聊消息给指定用户队列
群聊 用户队列动态绑定对应群聊 routing key,交换机广播群消息到所有成员队列
动态绑定解绑 用户加入或退出群聊时调用 RabbitMQ API 动态修改 routing key 绑定关系
WebSocket推送 消费者监听用户队列,实时推送消息到客户端 WebSocket
消息发送 客户端发消息到后端,由后端发布到交换机指定 routing key

如果需要,我还可以帮你写一份更详细的接口设计说明或配套代码示例。你看怎么样?

工具

ChatGPT 也可能会犯错。请核查重要信息。

空文件

简介

golang实现的聊天室系统 展开 收起
取消

发行版

暂无发行版

贡献者

全部

语言

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/coding_niann/go-chat.git
git@gitee.com:coding_niann/go-chat.git
coding_niann
go-chat
go-chat
master

搜索帮助