annidy / ginchat

基于gin的聊天服务

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ginchat

纸上得来终觉浅, 绝知此事要躬行

项目概述

本项目为基本的Gin+MySQL+Redis项目。核心的类在chat.go中。每一个用户登录后与后端有一个websocket长连接,通过长连接收发消息。所有消息都是json格式,通过Type区分是普通消息还是群消息,其他字段诸如Media表示消息内容格式,由前端负责处理。

所有消息都缓存在Redis中,用于用户上线后拉取最近消息(TODO:数据库没有用到)。为了方便实现,key = "msg"_type_uid1_uid2. 这里不区分发送放和接受方,因为接受方也需要读到同样的消息.

项目中使用一个map来存储所有连接,key是uid,value主要是websocket和管道。每次有用户连接后都会开启两个goroutine:

  1. 从ws读数据,解析为json后,把数据写到给其它node的管道中
  2. 从管道读数据,读取后往ws写数据,发给前端

这个设计对群发支持不太好,因为每次群发都需要枚举所有Node,加锁比较频繁。

这里面用到了一个udp服务做消息分发,也就是上面的routine 1其实先发到这个udp里,然后另一个routine这个udp再读取分发到其他Node。这样设计的好处是不再ws读取线程分发,减少前端对前端网络的阻塞。(这个设计还是可以的,只是这里应该用Redis的消息订阅和接受,不应该用UDP,它的缓存区太小,不能承受太多消息)

项目中有不少地方用到文件上传,这里因为服务本身也启动了静态文件服务,直接把上传的文件保存在upload目录了。

Swagger是个不错的工具,方便开发调试

表结构

  1. user_basic 用户信息表,主要存储用户ID、名称、密码登信息 TODO:用户密码没有加密,最好的方法是在数据库中引入一个Salt字段,前端返回的密码先加盐再MD5与本地数据库对比

  2. contacts 联系人表。这里联系人包括好友和群,群放到这里可能不太合适。

  3. community 群信息表,比较容易理解

  4. message 消息数据库,目前消息没有落库,只缓存在Redis中。

TODO

  1. 单机服务改为分布式
  2. 用户鉴权中间件。目前所有请求都没有鉴权
  3. 性能测试,看看这个能承受多少QPS

About

基于gin的聊天服务


Languages

Language:JavaScript 67.5%Language:CSS 23.9%Language:HTML 4.5%Language:PHP 1.7%Language:Go 1.2%Language:Less 1.0%Language:Shell 0.3%Language:Dockerfile 0.0%