25

Golang 写的即时通讯服务器 gim

 4 years ago
source link: https://github.com/alberliu/gim
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

简要介绍

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.不支持离线消息同步

核心流程时序图

长连接登录

iQB77jz.png!web

离线消息同步

bqi2Q3A.png!web

心跳

EJRvMva.png!web

消息单发

Nf22umN.png!web

消息群发

YZryQrN.png!web

github

https://github.com/alberliu/gim


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK