/zspchat

zsp系列下的一个聊天室,仿网页版qq/微信的一个im系统,打算整合一下最新学到的netty+kafka+MongoDB+rocket mq

zspchat

​ zspchat系列下的一个聊天网站,仿网页版qq/微信m统,以下会记录我每次更新迭代的想法:

  • 2021.11.8:目前要做的事是先把技术选型确定下来,以及梳理一个项目所要搭建的具体流程。
  • 2021.11.9:完成了技术选用,接下去梳理项目搭建流程。
    • 由于很久没写项目了,所以会花点时间在复习上。
    • 卡在了kafka日志收集整合过程中,正在解决。
  • 2021.11.28:建立了common依赖模块
  • 2021.12.26:发现对于netty的运用还不熟悉,正在努力学习

框架/技术选用

​ 传统的聊天工具都需要一个服务器,然后再建立客户端,对服务器端进行发送消息,然后让服务器端分发消息到指定的用户上。下面我们说一下选择使用的框架/技术。

Netty(聊天功能)

​ 使用netty的socket通信比起没有选择器的低效BIO和代码复杂、bug多的NIO来说,非常的惬意。netty是基于reactor模式下开发的一个NIO框架,整体更为规范。并且由于netty在不断的升级和迭代,目前API使用也特别舒服。

Kafka(日志采集)

​ Apache Kafka它最初由LinkedIn公司基于独特的设计实现为一个分布式的提交日志系统( a distributed commit log),之后成为Apache项目的一部分。

​ 原本打算全部用kafka作为消息中间件的,但kafka消费失败不支持重试,加之支持消息顺序,但是一台代理宕机后,就会产生消息乱序,这一系列缺点,都不适合我作为离线消息推送到持久层的中间件,所以我这里采用kafka作为日志采集工具。

Rocket MQ(离线消息推送、订阅消息,目前还没学)

​ Rocket MQ出自 阿里公司的开源产品,用 Java 语言实现,在设计时参考了 Kafka,并做出了自己的一些改进。RocketMQ在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。

  • MQ功能较为完善,还是分布式的,扩展性好

  • 支持10亿级别的消息堆积,不会因为堆积导致性能下降

  • 源码是java,不像rabbit mq,无法定制。

    唯一的缺点就是,我还没学过rocket mq,不过问题不大,给我一礼拜。

MongoDB(历史消息存储)

以前的项目一直用的都是mysql、sql server作为持久层的,一直用的都是关系型数据库。非关系型数据库,例如redis、ES一般就只有用来做为缓存或者是sql同步做联合搜索使用。mongodb是我给我家臭小露讲怎么用的时候凑巧学了一点的,可以说一面之缘,但其一直位于非关系型数据库榜首,而且我没用用过非关系型数据库作为持久层过,这次就使用一下。

  • 虚拟内存(cpu)+持久化(磁盘)
  • 在适量级的内存的MongoDB的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快。
  • MongoDB的高可用和集群架构拥有十分高的扩展性。
  • 在副本集中,当主库遇到问题,无法继续提供服务的时候,副本集将选举一个新的主库继续提供服务。

Redis(缓存、spring session)

讲一嘴吧,我会用spring session作为用户登录状态的验证功能,查找到用户不在线的话会直接同步消息到持久层上,如果用户在线则直接进行消息发送,当一方离线后,会将消息发送到rocket mq,然后再由定时任务一次性发送到持久层上。

AUTH2.0

原本想把这个网站挂到服务器上的,但是好像。。。又做成分布式了,索性就还是分布式吧,用auth2.0作为分布式认证中心。

流程设计图

​ 整体功能打算设计成:私聊和群发。

  • 私聊:消息发送至服务端时,携带对方的id或者对方的账号信息,以此作为私聊和群发的区别点
    • 检测在线:私聊最重要的一点就是检测对方是否在线
      • 对方在线:只需要使用服务器端转发消息给对方即可(可能在心跳检测期间离线,所以消息记录做了漫游)
      • 对方不在线:只需要使用服务器端转发消息给对法
    • 聊天记录:聊天记录在登陆后,会校准数据库,当本地消息和数据库不匹配使用数据库消息(数据库只存储三天内的消息)
      • 本地保存:使用IO将聊天记录写在本地存储文件上
      • 消息漫游:为了防止出现心跳检测期间用户离线导致消息丢失,所以当用户聊天结束后会被发送到MQ中,再由MQ发到数据库中。(这里用到了Rocket MQ削峰填谷的特点)
  • 群消息:每一次发送携带群号消息,或者是群的ID消息发送。
    • 群消息发送:分为两种情况
      • 群成员在线:在线直接接收到后,直接IO到用户本地。
      • 群成员离线:将消息推送到MQ,MQ使用订阅模式发送到当时为离线状态的用户上(MQ仅存储三天内的消息)

zspchat流程图

整体架构图

​ 因为是微服务框架,所以这里以模块功能为划分点:

zspchat架构图