设计思想
入口网关子服务是整个聊天室唯一面向客户端的服务 ,不对外提供任何业务逻辑,只承担三件事:HTTP 接入与分发、登录会话鉴权、WebSocket 长连接推送。服务启动时先构造 Redis 客户端(承载登录会话与在线状态),再以服务根目录为监控范围创建服务发现客户端,把文件存储、语音识别、消息存储、好友管理、用户管理、消息转发六个子服务 全部登记为管理目标,并注册服务上线与服务下线回调------子服务实例上下线时自动增删对应信道,调用时从当前可用节点中轮转选择;随后创建 HTTP 服务器与 WebSocket 服务器,把 30 个业务接口按路径逐一注册为 HTTP POST 处理函数,并监听对应的 HTTP 端口与 WebSocket 端口。网关自身不注册到注册中心 ------它只消费注册中心里的服务信息。运行期有两条链路:HTTP 链路 上,客户端一律以 POST 方式提交 protobuf 二进制正文,网关先反序列化、再从 Redis 中校验登录会话取出用户身份(注册、登录、验证码三类接口免鉴权),随后从信道管理中选出对应子服务的节点发起 brpc 调用,把子服务的响应序列化后回写为 HTTP 响应;WebSocket 链路上,客户端连接建立后发送首帧身份识别信息,网关反序列化出登录会话 ID 并到 Redis 中查证,查不到则直接关闭连接,查到则把该连接登记进长连接管理(维护用户 ID 与连接的映射),此后由网关按子服务返回的目标用户 ID 找到对应连接并推送通知------好友申请、申请处理结果、好友删除、会话建立与新消息五类通知皆由此发出。连接断开时,网关从 Redis 中删除该会话与在线状态,并从长连接管理中移除连接。

功能设计
网关服务器在设计中,最重要的两个功能:
- 作为入口服务器接收客户端的所有请求,进行请求的子服务分发,得到响应后进行响应
- 对客户端进行事件通知(好友申请和处理及删除,单聊 / 群聊会话创建,新消息)
基于以上的两个功能,因此网关服务器包含两项通信:
- HTTP 通信:进行业务处理
- WEBSOCKET 通信:进行事件通知
模块划分:
- 参数 / 配置文件解析模块:基于 gflags 框架直接使用进行参数 / 配置文件解析。
- 日志模块:基于 spdlog 框架封装的模块直接使用进行日志输出。
- rpc 服务发现与调用模块:基于 etcd 框架与 brpc 框架封装的服务发现与调用模块 a. 因为要分发处理所有请求,因此所有的子服务都需要进行服务发现。
- redis 客户端模块:基于 redis++ 封装的客户端端进行内存数据库数据操作 a. 根据用户子服务添加的会话信息进行用户连接身份识别与鉴权
- HTTP 通信服务器模块:基于 cpp-httplib 库搭建 HTTP 服务器,接收 HTTP 请求进行业务处理。
- WEBSOCKET 服务器模块:基于 Websocketpp 库,搭建 websocket 服务器,进行事件通知。
- 客户端长连接管理模块:建议用户 ID 与长连接句柄映射关系,便于后续根据用户 ID 找到连接进行事件通知
接口实现流程:


用户名注册
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
用户名登录
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
短信验证码获取
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
手机号码注册
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
手机号码登录
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
用户信息获取
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
修改用户头像
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
修改用户签名
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
修改用户昵称
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
修改用户绑定手机号
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
获取好友列表
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
发送好友申请
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 根据请求中的用户 ID,调用用户子服务,获取用户的详细信息
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 若处理成功,则通过被申请人 ID,查找对方长连接 a. 若长连接存在(对方在线),则组织好友申请通知进行事件通知
- 将处理结果响应给客户端。
获取待处理好友申请
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
好友申请处理
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找用户子服务
- 根据请求中的用户 ID,调用用户子服务,获取申请人与被申请人的详细信息
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 若处理成功,则通过申请人 ID,查找申请人长连接,进行申请处理结果的通知 a. 若处理结果是同意,则意味着新聊天会话的创建,则对申请人继续进行聊天会话创建通知 i. 从处理结果中取出会话 ID,使用对方的昵称作为会话名称,对方的头像作为会话头像组织会话信息 b. 若处理结果是同意,则对当前处理者用户 ID 查找长连接,进行聊天会话创建的通知 i. 从处理结果中取出会话 ID,使用对方的昵称作为会话名称,对方的头像作为会话头像组织会话信息 c. 清理响应中的会话 ID 信息
- 将处理结果响应给客户端
删除好友
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 若处理成功,则通过被删除者用户 ID,查找对方长连接 a. 若长连接存在(对方在线),则组织好友删除通知进行事件通知
- 将处理结果响应给客户端。
搜索用户
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
获取用户聊天会话列表
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
创建多人聊天会话
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 若处理成功,循环根据会话成员的 ID 找到他们的长连接 a. 根据响应中的会话信息,逐个进行会话创建的通知 b. 清理响应中的会话信息
- 将处理结果响应给客户端。
获取消息会话成员列表
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找好友子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
发送新消息
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找消息转发子服务
- 调用子服务对应接口进行业务处理
- 若处理成功,则根据处理结果中的用户 ID 列表,循环找到目标长连接,根据处理结果中的消息字段组织新消息通知,逐个对目标进行新消息通知。
- 若处理失败,则根据处理结果中的错误提示信息,设置响应内容
- 将处理结果响应给客户端。
获取指定时间段消息列表
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找消息存储子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
获取最近 N 条消息列表
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找消息存储子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
搜索关键字历史消息
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找消息存储子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
单个文件数据获取
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找文件子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
多个文件数据获取
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找文件子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
单个文件数据上传
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找文件子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
多个文件数据上传
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找文件子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。
语音转文字
- 取出 HTTP 请求正文,进行 ProtoBuf 反序列化
- 根据请求中的会话 ID 进行鉴权,并获取用户 ID,向请求中设置用户 ID
- 查找语音子服务
- 调用子服务对应接口进行业务处理
- 将处理结果响应给客户端。需要我把这一整段和前面【功能设计、模块划分、架构图说明】合并成一份完整报告文本吗?

