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仅存储三天内的消息)
- 群消息发送:分为两种情况
整体架构图
因为是微服务框架,所以这里以模块功能为划分点: