纸上得来终觉浅, 绝知此事要躬行
本项目为基本的Gin+MySQL+Redis项目。核心的类在chat.go中。每一个用户登录后与后端有一个websocket长连接,通过长连接收发消息。所有消息都是json格式,通过Type区分是普通消息还是群消息,其他字段诸如Media表示消息内容格式,由前端负责处理。
所有消息都缓存在Redis中,用于用户上线后拉取最近消息(TODO:数据库没有用到)。为了方便实现,key = "msg"_type_uid1_uid2. 这里不区分发送放和接受方,因为接受方也需要读到同样的消息.
项目中使用一个map来存储所有连接,key是uid,value主要是websocket和管道。每次有用户连接后都会开启两个goroutine:
- 从ws读数据,解析为json后,把数据写到给其它node的管道中
- 从管道读数据,读取后往ws写数据,发给前端
这个设计对群发支持不太好,因为每次群发都需要枚举所有Node,加锁比较频繁。
这里面用到了一个udp服务做消息分发,也就是上面的routine 1其实先发到这个udp里,然后另一个routine这个udp再读取分发到其他Node。这样设计的好处是不再ws读取线程分发,减少前端对前端网络的阻塞。(这个设计还是可以的,只是这里应该用Redis的消息订阅和接受,不应该用UDP,它的缓存区太小,不能承受太多消息)
项目中有不少地方用到文件上传,这里因为服务本身也启动了静态文件服务,直接把上传的文件保存在upload目录了。
Swagger是个不错的工具,方便开发调试
-
user_basic 用户信息表,主要存储用户ID、名称、密码登信息 TODO:用户密码没有加密,最好的方法是在数据库中引入一个Salt字段,前端返回的密码先加盐再MD5与本地数据库对比
-
contacts 联系人表。这里联系人包括好友和群,群放到这里可能不太合适。
-
community 群信息表,比较容易理解
-
message 消息数据库,目前消息没有落库,只缓存在Redis中。
- 单机服务改为分布式
- 用户鉴权中间件。目前所有请求都没有鉴权
- 性能测试,看看这个能承受多少QPS