一、系统架构
- goim:长连接系统,实现了单播、多播、广播功能
- imService:聊天服务器,处理私聊消息
- redis:用于订阅、发布用户上下线消息,存储用户已同步的最大消息id
- mysql:存储私聊消息,作为收信箱和发信箱
二、实现方式
2.1 设计目标
2.2 在线消息
2.3 离线消息
2.4 消息确认
三、数据模型
CREATE TABLE `hl_single_chat` (
`id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`msg_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '消息id',
`from` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '消息发送者',
`to` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '消息接收者',
`body` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '聊天消息',
`msg_type` tinyint(2) NOT NULL DEFAULT '1' COMMENT '消息内容 0 表示文本消息 1 表示 图片',
`deleted` tinyint(3) NOT NULL DEFAULT '0' COMMENT '是否删除 0 正常 1已删除',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `to` (`to`)
) ENGINE=InnoDB AUTO_INCREMENT=114 DEFAULT CHARSET=utf8 COMMENT='私聊收信箱';
复制代码
四、接口设计
4.1 接口说明
序号 |
接口 |
说明 |
备注 |
1 |
sendMsg |
发送消息 |
http协议,给用户发送点对点普通消息,包括文本,图片,语音,视频,地理位置和自定义消息。 |
2 |
ackMsg |
消息确认 |
http协议,客户端确认已收到最msgId,若收到的消息不连续,发送连续区间的最大msgId到服务器,服务器重新下发 |
3 |
syncMsg |
同步消息 |
http协议,若客户端收到的消息不连续,调用此接口同步丢失的消息区间 |
4 |
push |
|
下发消息,对应SingleChatMsg协议 |
4.2 发送消息接口(/api/chat/singleChat/v1/sendMsg)
4.2.1 请求参数
参数名称 |
参数类型 |
|
备注 |
from |
long |
|
接收消息的用户uid |
to |
long |
|
发送消息的用户uid |
msgType |
int |
|
0 表示文本消息 1 表示图片 |
body |
string |
|
最大长度5000字符,JSON格式。见消息格式示例 |
- A发送消息给B,A,B都会收到服务器下发的消息,A收到消息的from=A,to=A。
- B收到的消息 from=A,to=B
消息格式示例
1.文本消息
{
"msg":"哈哈哈"//消息内容
}
复制代码
2.图片消息(type = 1)
{
"name":"图片发送于2015-05-07 13:59", //图片name
"md5":"9894907e4ad9de4678091277509361f7", //图片文件md5
"url":"http://nimtest.nos.netease.com/cbc500e8-e19c-4b0f-834b-c32d4dc1075e", //生成的url
"ext":"jpg", //图片后缀
"w":6814, //宽
"h":2332, //高
"size":388245 //图片大小
}
复制代码
4.2.2 响应示例
{
"code": 200,
"data": null,
"msg": "成功",
"time": 1580636467231
}
复制代码
4.3 消息确认(/api/chat/singleChat/v1/ackMsg)
4.3.1 请求参数
参数名称 |
参数类型 |
示例 |
备注 |
uid |
long |
|
用户uid |
msgId |
long |
|
已收到的最大消息id |
4.3.2 响应示例
{
"code": 200,
"data": null,
"msg": "成功",
"time": 1580636467231
}
复制代码
4.4 同步消息(/api/chat/singleChat/v1/sync)
4.4.1 请求参数
参数名称 |
参数类型 |
示例 |
备注 |
uid |
long |
|
用户uid |
begin |
long |
|
需要同步的消息区间的开始位置 |
end |
long |
|
需要同步的消息区间的结束位置 |
4.4.2 响应示例
{
"code": 200,
"data": [
{
"id": 104,
"msgId": 25,
"from": 90000009,
"to": 90000009,
"msgType": 0,
"body": "{\"msg\":\"哈哈哈\"}",
"deleted": 0,
"createTime": "2020-02-02T09:30:42.000+0000",
"updateTime": "2020-02-02T09:30:42.000+0000"
},
{
"id": 106,
"msgId": 26,
"from": 90000009,
"to": 90000009,
"msgType": 0,
"body": "{\"msg\":\"哈哈哈\"}",
"deleted": 0,
"createTime": "2020-02-02T09:40:49.000+0000",
"updateTime": "2020-02-02T09:40:49.000+0000"
},
{
"id": 108,
"msgId": 27,
"from": 90000009,
"to": 90000009,
"msgType": 0,
"body": "{\"msg\":\"哈哈哈\"}",
"deleted": 0,
"createTime": "2020-02-02T09:40:51.000+0000",
"updateTime": "2020-02-02T09:40:51.000+0000"
},
{
"id": 110,
"msgId": 28,
"from": 90000009,
"to": 90000009,
"msgType": 0,
"body": "{\"msg\":\"哈哈哈\"}",
"deleted": 0,
"createTime": "2020-02-02T09:40:52.000+0000",
"updateTime": "2020-02-02T09:40:52.000+0000"
},
{
"id": 112,
"msgId": 29,
"from": 90000009,
"to": 90000009,
"msgType": 0,
"body": "{\"msg\":\"哈哈哈\"}",
"deleted": 0,
"createTime": "2020-02-02T09:41:07.000+0000",
"updateTime": "2020-02-02T09:41:07.000+0000"
}
],
"msg": "成功",
"time": 1580636469698
}
复制代码
4.5 下发消息
// MaxType是大类型所有可能的取值。
enum MaxType {
MaxType_DO_NOT_USE = 0;
ROOM = 1; // 直播间消息 RoomMsg
GIFT = 2; // 礼物消息
SINGLE_CHAT = 3; //单聊消息
}
// ServerPush是服务端推送到客户端的最外层协议包
message ServerPush {
MaxType messageType = 1; // 大类型 MaxType
bytes pushBuffer = 2; // 内层协议(小类型和消息内容)
map<string, string> headers = 3;
string messageDesc = 4; // 可选,调试用
string serviceName = 5; // 可选,调试用
string methodName = 6; // 可选,调试用
}
enum MinTypeSingleChat {
Text = 0; //文本
Image = 1; // 图片
}
// 私聊消息
message SingleChatMsg{
int64 msgId = 1;
int64 from = 2;
int64 to = 3;
MinTypeSingleChat type = 4; //消息类型 0 文本 1 图片
string body = 5; //消息内容
int64 createTime = 6; //消息发送时间
}
复制代码