背景
作为平台,有个常用的功能是系统内部通知,即系统内部生成并管理的消息。这些消息是由系统的各个业务功能自动触发的。以订单发货为例,当一个订单完成发货流程后,系统会自动生成一条消息,并立即通知到下单的用户。这一通知的过程是通过消息推送机制实现的,确保了用户能够实时接收到相关信息。
被通知的用户在其界面上会有明显的感知。在他们的浏览器界面右下角,会弹出一个消息提醒,告知他们有新的消息待查看。同时,浏览器右上角的消息图标也会显示未读消息的数量,这样用户可以一目了然地知道有多少新消息等待他们处理。
为了实现这一实时消息推送功能,我们采用了先进的Web Socket技术。与传统的浏览器端定时轮询方式相比,Web Socket提供了更为高效和实时的数据传输机制。通过建立一个持久的连接,Web Socket允许服务器主动向客户端发送数据,无需客户端频繁地发起查询请求。这不仅降低了服务器的负载,还为用户带来了更为流畅和及时的消息体验。
是否支持用户间互发消息
此处功能规划专用于上述系统事件发生时发送消息给用户,不考虑用户之间的互发消息,用户之间的信息沟通,根据实际情况选择通知公告或者专门的即时通信工具更合适。
单用户同时登录多客户端的处理策略
首先技术上可以做到,允许每个用户同时登录多个客户端(此处指浏览器),创建多个websocket长连接,推送消息时推送到所有channel,实际业务场景,存在多人用公用账号进行业务处理的场景,如值班,因此推送至所有客户端。
心跳机制策略
之前实现的系统间对接,采用的心跳机制是客户端发送心跳请求,服务端收到心跳请求立即回复,客户端来监控心跳超时以及自动重连。
对于浏览器websocket场景,可能会存在客户端直接强制退出(关浏览器或杀死进程),这种情况下,服务端是收不到通道关闭的消息。
为避免失效连接长期存在,采取进一步的辅助策略:由服务器端检测,设置一个读写均空闲的时间(比如30秒),如触发了空闲事件,则说明客户端已经没有心跳或者数据发送了,这时候主动关闭连接。
消息类型
前后端交互的消息有以下几种:
- 前端发送登录请求消息
- 前端发送心跳请求消息
- 前端发送注销请求消息
- 后端发送登录响应消息
- 后端发送心跳响应消息
- 后端发送业务消息
注:收到前端的注销请求无需再发送响应给前端,直接关闭通道即可
未读消息数量的计算
- 从后端服务读取,作为初始值
- 新收到消息,加1
- 查看单条消息,若消息状态为未读则减1
- 全部已读,置0
- 删除多条消息,重新读取
- 删除单条消息,若消息状态为未读则减1
是否需要消息确认与重发
为保证业务消息稳定可靠传递,通常进行消息确认,对未收到确认的进行重发,这种方式适合系统与系统之间传递消息。但是系统内置消息通知,场景有差异。首先,对消息的可靠性要求并不高,因为业务消息会持久化,用户登录系统或刷新页面时,仍会看到所有的消息。基于该视角,不进行消息的确认与重发。
轮询方式与web socket方式对比
轮询方式实现简单,但是需要发起大量的查询请求,并且实时性上有缺失(延迟性低则要求轮询间隔短,请求频率高)。
web socket方式实现简单,首先保证了实时性,其次,关于资源消耗情况,粗略一看,心跳仍需定时发送,并保持了大量长连接,但细想一下,心跳并不需要高频率,可以30秒甚至 5分钟都可以,因为消息是实时发送的,降低心跳发送频率并不能影响实时性,此外,心跳请求和确认直接按约定报文处理即可,过程中并不涉及业务处理,也不包括数据库读写操作,因此性能上没问题。