简要介绍
gim 是一个即时通讯服务器, 代码全部使用 golang 完成. 主要功能
1. 离线消息同步
2. 多业务接入
3. 单用户多设备同时在线
4. 单聊, 群聊, 以及超大群聊天场景 5. 支持服务水平扩展
使用技术:
数据库: MySQL+Redis
组件: grpc+jsoniter+zap
安装部署
1. 首先安装 MySQL,Redis
2. 创建数据库 gim, 执行 sql/create_table.sql, 完成初始化表的创建 3. 下载代码到你本地 4. 修改 conf/conf.go 配置文件, 使之和你本地配置一致
5. 分别切换到 App 的 connect 和 logic 目录下, 执行 go run main.go, 启动连接层服务器和逻辑层服务器
6. 切换到 test 目录下, 启动测试脚本
7. 使用 public/util/aes.go 的 GetToken 获取 token
8. 使用 rpc 接口发送消息
业务服务器如何接入
1. 首先生成私钥和公钥 2. 在 App 表里根据你的私钥添加一条 App 记录
3. 将 app_id 和公钥保存到业务服务器
4. 将用户通过 LogicClientExtServer.AddUser 接口添加到 IM 服务器 5. 通过 LogicClientExtServer.RegisterDevice 接口初始化设备, 获取设备 id(device_id) 6. 将 app_id,user_id,device_id 用公钥通过公钥加密, 生成 token, 相应库的代码在 public/util/aes.go
7. 接下来使用这个 token,App 就可以和 IM 服务器交互
项目目录介绍
├─ App # 服务启动入口
│ ├── conn # 连接层启动入口
│ └── logic # 逻辑层启动入口
├─ conf # 配置
├─ conn # 连接层服务代码
├─ ligic # 逻辑层服务代码
├─ public # 连接层和逻辑层公共代码
├─ sql # 数据库建表语句
├─ test # 测试脚本
├─ docs # 项目文档
TCP 拆包粘包
遵循 TLV 的协议格式, 一个消息包分为三部分, 消息类型 (两个字节), 消息包内容长度 (两个字节), 消息内容.
这里为了减少内存分配, 拆出来的包的内存复用读缓存区内存.
拆包流程:
1. 首先从系统缓存区读取字节流到 buffer
2. 根据包头的 length 字段, 检查报的 value 字段的长度是否大于等于 length
3. 如果大于, 返回一个完整包 (此包内存复用), 重复步骤 2
4. 如果小于, 将 buffer 的有效字节前移, 重复步骤 1
服务简介
1.connect
维持与客户端的 TCP 长连接, 心跳, 以及 TCP 拆包粘包, 消息编解码 2.logic
消息转发逻辑, 设备信息, 用户信息, 群组信息的操作
离线消息同步
用户的消息维护一个自增的序列号, 当客户端 TCP 连接断开重新建立连接时, 首先要做 TCP 长连接的登录, 然后用客户端本地已经同步的最大的序列号做消息同步, 这样就可以保证离线消息的不丢失.
单用户多设备支持
当用户发送消息时, 除了将消息发送目的用户
在 DB 中, 每个用户只维护一个自己的消息列表, 但是用户的每个设备各自维护自己的同步序列号, 设备使用自己的同步序列号在消息列表中做消息同步
消息转发逻辑
单聊和普通群组采用写扩散, 超级大群使用读扩散.
读扩散和写扩散的选型.
首先解释一下, 什么是读扩散, 什么是写扩散
读扩散
简介: 群组成员发送消息时, 也是先建立一个会话, 都将这个消息写入这个会话中, 同步离线消息时, 需要同步这个会话的未同步消息
优点: 每个消息只需要写入数据库一次就行, 减少数据库访问次数, 节省数据库空间
缺点: 一个用户有 n 个群组, 客户端每次同步消息时, 要上传 n 个序列号, 服务器要对这 n 个群组分别做消息同步
写扩散
简介: 就是每个用户维持一个消息列表, 当有其他用户给这个用户发送消息时, 给这个用户的消息列表插入一条消息即可
优点: 每个用户只需要维护一个序列号和消息列表
缺点: 一个群组有多少人, 就要插入多少条消息, 当群组成员很多时, DB 的压力会增大
群组简介
普通群组:
1. 支持离线消息同步
2. 群组成员越多, DB 压力越大
超大群组:
1.DB 压力不会随着群组成员的人数的增加而增加
2. 不支持离线消息同步
核心流程时序图
长连接登录
离线消息同步
心跳
消息单发
消息群发
- GitHub
- https://github.com/alberliu/gim
来源: http://www.tuicool.com/articles/yUbimeU