1. 系统架构
1.1. 技术选型
l protobuf
Client与好友系统服务端程序之间,以及服务端各内部组件间均采用protobuf定义通信协议。
Client与服务端之间的交互消息仍然沿用现有的网狐格式,只是将网狐数据包中的消息体部分由C++结构换成protobuf定义。
l pika
pika兼容redis的核心数据类型以及操作协议,同时支持数据持久化到磁盘。
这里使用pika替代redis主要用于:
1) 持久化存储好友系统涉及到的用户基本信息、用户间好友关系、用户在线状态等
2) 保存好友申请信息列表
3) 缓存离线消息
4) 用作消息队列中间件使用
1.2. 整体架构
核心组件与主要流程:
1) Client从第一个WebAPI返回数据中获得聊天网关地址列表
2) Client登录成功后,尝试连接好友系统的接入网关gateway (轮询网关列表,直到成功建立TCP连接,并成功登录ChatServer)。每个gateway与业务路由ChatRouter之间建立一个TCP连接。
3) Client与好友系统Server端的所有业务交互,好友间的聊天消息,都通过gateway程序转发给ChatRouter,然后ChatRouter根据业务请求类型,分发给不同的业务服务器进行处理
4) ChatRouter(即聊天系统业务路由程序),位于接入网关gateway与聊天服务器(集群)之间,负责业务请求的分发及业务处理结果及聊天消息的回传处理
5) 聊天服务器集群由以下组件构成:
a. ChatServer
聊天系统主服务器:负责处理DataServer下发的新用户信息、用户状态变化、用户积分、游戏数据的同步处理等。
b. MsgProcessor
聊天消息处理程序:负责处理用户发送的聊天消息。根据用户当前在线状态确定是投递到待发送消息的MQ中,还是存入pika离线消息列表中。
c. MsgSender
聊天消息发送程序:负责从MQ中加载待发送消息,并完成消息发送。
6) DataSync(待定)
负责用户信息存量数据的同步:将DB中的用户基本信息、游戏统计数据等同步到Pika NoSQL缓存数据库中。
(待定:考虑只在用户登录DataServer时,通过ChatServer同步用户信息到pika缓存?)
2. DB设计
2.1. 接入网关信息表
RYPlatformDB.dbo.ChatGatewayInfo
字段名称 |
中文描述 |
数据类型 |
备注 |
ID |
网关ID |
integer |
非自增唯一ID,添加时Web自动生成下一个可用ID,可编辑修改,但需要校验唯一性 |
PublicIP |
公网IP |
string |
网关公网IP地址 |
Port |
端口 |
integer |
网关服务端口 |
RouterID |
业务路由ID |
integer |
默认为0,对应的业务路由ID(下拉列表),添加时可选填,之后可编辑修改 |
2.2. 业务路由信息表
RYPlatformDB.dbo.ChatRouterInfo
字段名称 |
中文描述 |
数据类型 |
备注 |
ID |
路由ID |
integer |
非自增唯一ID,添加时Web自动生成下一个可用ID,可编辑修改,但需要校验唯一性 |
LocalIP |
内网IP |
string |
内网IP地址 |
Port |
端口 |
integer |
服务端口 |
2.3. 聊天服务信息表
RYPlatformDB.dbo.ChatServerInfo
字段名称 |
中文描述 |
数据类型 |
备注 |
ID |
服务器ID |
integer |
非自增唯一ID,添加时Web自动生成下一个可用ID,可编辑修改,但需要校验唯一性 |
ServerType |
类型 |
integer |
单选按钮:1 ChatServer, 2 MsgProcessor, 3 MsgSender |
LocalIP |
内网IP |
string |
内网IP地址 |
Port |
端口 |
integer |
服务端口 |
2.4. 敏感词汇信息表
RYPlatformDB.dbo.ChatForbiddenWords
字段名称 |
中文描述 |
数据类型 |
备注 |
en |
英语 |
string |
|
es |
西班牙语 |
string |
|
pt |
葡萄牙语 |
string |
3. pika缓存设计
3.1. 用户信息
使用HashSet存储用户信息。
【key】:
“userid:” + <userid>
【示例】:
以userid=100001用户为例,其用户信息等价的json内容为:
{
"user:100001":{
"userid":100001,
"nickname":"test",
"faceid":1,
"faceurl":"",
"facebookid":"",
"viplevel":1,
"wincount":1,
"lostcount":1
}
}
3.2. 好友关系
使用Set存储用户的好友、黑名单信息
3.2.1. 好友列表
【key】:
“user:” + <userid> + “:friends”
【示例】:
向userid为100001用户添加好友100002,操作为:
sadd user:100001:friends 100002
3.2.2. 黑名单列表
【key】:
“user:” + <userid> + “:blacklist”
【示例】:
向userid为100001用户添加黑名单100003,操作为:
sadd user:100001:blacklist 100003
3.3. 好友申请列表
每个好友申请分配一个唯一的序列号作为friendrequestid,使用一个全局的hashset存储所有好友申请列表。
然后,一个好友申请对应的发起申请的用户和被邀请加好友的用户各自关联到相同的friendrequestid。
全局好友申请列表hashset如下:
【key】:
“friendrequest:” + <requestid>
【示例】:
hmset friendrequest:1 from 100001 to 100002 time 1683600098 status 0
sadd user:100001:friendrequests 1
sadd user:100002:friendrequests 1
3.4. 在线用户列表
使用set存储在线用户列表:
sadd onlineusers 100001
3.5. 离线消息
使用list存储离线消息:
lpush user:110001:offlinemsgs {“from”:100001,”to”:110001,”msg”:”test msg”}
3.6. 待发送消息
使用list作为消息队列存储待发送消息
【写消息】:
lpush msgs {“from”:100001,”to”:100002,”msg”:”test msg”}
【读消息】:
rpop msgs
4. Web
4.1. 系统配置
4.1.1. 菜单项变更
1) 新增菜单项:
系统维护 > 好友系统
2) 好友系统配置页面包含5个TAB页:
l 参数设置
l 业务路由
l 接入网关
l 聊天服务
l 敏感词汇
4.1.2. 参数设置
1) 数据表:RYPlatformDB.dbo.ServerParam
2) 编辑界面如下:
好友申请过期时间: |
3 (单位:天,Name=”ADD_FRIEND_EXPIRATION”) |
离线消息保留时长: |
7 (单位:天,Name=”OFFLINE_MESSAGE_EXPIRATION”) |
最大消息长度: |
200 (单条消息最大字数,Name=MAX_CHAT_MESSAGE_LENGTH”) |
4.1.3. 业务路由
1) 数据表:RYPlatformDB.dbo.ChatRouterInfo
2) 编辑界面如下:
路由ID: |
1 (字段:ID) |
内网IP: |
192.1.1.1 (字段:LocalIP) |
端口: |
3001 (字段:Port) |
3) 需提供增、删、改、浏览功能
4.1.4. 接入网关
1) 数据表:RYPlatformDB.dbo.ChatGatewayInfo
2) 编辑界面如下:
网关ID: |
1 (字段:ID) |
公网IP: |
100.1.1.1 (字段:PublicIP) |
端口: |
3001 (字段:Port) |
业务路由: |
下拉列表选择 (来源于ChatRouterInfo表),列表中显示:未选择、及业务路由信息的IP,Port,如:10.1.1.1,8000 |
3) 需提供增、删、改、浏览功能
4.1.5. 聊天服务
1) 数据表:RYPlatformDB.dbo.ChatServerInfo
2) 编辑界面如下:
服务器ID: |
1 (字段ID) |
服务类型: |
单选按钮(字段:ServerType,取值: 1 ChatServer, 2 MsgProcessor, 3 MsgSender) |
内网IP: |
100.1.1.1 (字段:LocalIP) |
端口: |
5001 (字段:Port) |
3) 需提供增、删、改、浏览功能
4.1.6. 敏感词汇
1) 数据表:RYPlatformDB.dbo.ChatForbidenWords
2) 界面如下:
英语: |
shit (字段:en) |
西班牙语: |
mierda(字段:es) |
葡萄牙语: |
merda(字段:pt) |
4.2. WebAPI
Client调用的第一个WebAPI应答消息中增加好友系统的参数设置,如下所示:
{
"data":{
"Theversion":0,
⁝
"chat":{
"maxchatmessagelength":200,
"gateways":[
{
"ip":"1.1.1.1",
"port":10001
},
{
"ip":"1.1.1.1",
"port":10002
}
]
}
}
}
【字段说明】:
maxchatmessagelength:单条消息的最大长度
【注】:
1. Client只有在登录成功后,才能发起与接入网关之间的TCP连接
2. Client与网关之间为TCP长连接,进游戏房间后,仍保持与网关之间的连接
3. 登录成功后,client需从网关地址列表中随机挑选一个地址尝试连接,若连接失败,则依次顺序尝试连接下一个地址
4. client与网关成功建立连接后,若收发消息出错/超时,则client关闭当前到网关的TCP连接,然后向列表中的下一个网关地址发起重连
5. Client与Server端(聊天服务器集群)交互消息定义
Client与Server端(聊天服务器集群)间交互消息采用protobuf。
具体消息定义请参考项目工程目录下的proto定义文件:protogen/proto/chat.proto。