前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >websocket消息推送设计

websocket消息推送设计

作者头像
lyb-geek
发布2022-11-18 14:52:51
4.3K0
发布2022-11-18 14:52:51
举报
文章被收录于专栏:Linyb极客之路Linyb极客之路

1. 背景

公司内目前有几个项目都有消息推送的功能,例如:某个业务操作之后需要推送消息给前端页面,让用户实时感知。

但是目前公司内的消息推送实现分散在在各个项目中,与业务系统强耦合,如果有其他项目需要集成消息推送功能,需要重复开发。故对消息推送功能进行公共抽取实现,提供一个通用的消息推送服务供各项目使用,减少重复开发,并且统一管控,做到降本增效。

消息推送是消息中心里重要的一环,会作为消息中心的一个模块进行设计开发实现。

主要定位是:致力于为公司各项目提供接入简单、可靠、安全稳定、快速实时推送服务。

2.特性

2.1 分布式

消息推送是消息中心里重要的一环,会作为消息中心的一个模块进行设计开发实现。

消息中心是多节点集群部署,支持水平扩展,保证推送能力可用性。

2.2 接入简便

消息中心提供统一推送api供应用方调用,引入依赖,配置消息中心地址即可。

2.3 统一实现

无需重复开发,统一消息推送技术栈,实现长连接管理和推送能力,便于功能迭代和维护,并作为基础技术能力沉淀。

2.4 解耦

业务系统和推送能力解耦,让业务方专注业务,不用关心推送实现细节。

2.5 监控

采用Prometheus+Grafana对推送服务的各项指标进行监控展示,并对异常进行报警。保证推送能力稳定性。

并且在线人数、连接数可观测。

2.6 可靠

提供心跳检测,及时重连和释放连接。保证消息不丢失,不重复推送,离线消息推送,消息补发。

2.7 并发

内部采用mq进行异步处理,支撑较高并发。

2.8 性能

内部采用forkjoin并发处理模型、缓存等手段避免耗时长的代码,提升推送效率。

3. 技术调研

下面主要介绍 web 端主要的四种消息推送方式。

3.1 短轮询

短轮询指的是前端页面每隔一定时间定时调用服务端的 HTTP 请求(如每1秒),之后由服务端返回最新的数据给前端页面。因为HTTP协议是一种无状态的、基于TCP的请求/响应模式的协议,请求只能由客户端发起然后服务端进行响应。

这种方式是实现最简单的。缺点是大部分请求是无效的,浪费了带宽和服务器资源。如果间隔很小,会对服务端造成比较大的压力。

3.2 长轮询

长轮询是前端页面向服务端发送一次 ajax 请求,服务端收到请求后保持连接,直到有新消息才返回响应并关闭连接,并且处理完响应信息后再向服务端发送新的请求

长轮询的优点很明显,在服务端没有消息的情况下不会频繁的请求,实现了服务端主动向前端推送的功能。但是服务端保持连接会消耗资源、返回数据顺序无保证、难于管理维护。(webQQ 就是使用了基于comet的长轮询技术)

3.3 Server-Sent Events

服务器发送事件是 HTML5 规范中提供的服务端事件 EventSource,浏览器在实现了该规范的前提下创建一个EventSource 连接后,便可收到服务端的发送的消息,实现一个单向通信。它类似于长轮询的机制,但是它在每一次的连接中,不只等待一次数据的更动。客户端发送一个请求到服务端 ,服务端保持这个请求直到一个新的消息准备好,将消息返回至客户端,此时不关闭连接,仍然保持它,供其它消息使用。

该方式的优点就是重复利用一个连接来处理每一个消息,缺点是只能服务端向客户端推送,并不是所有浏览器都支持。

3.4 WebSocket方案

webSocket 是 HTML5 下的一种新协议,是基于TCP的应用层协议,只需要一次连接,便可以实现全双工通信,即客户端和服务端可以相互主动发送消息。

该方式是目前服务端推送技术的主流方案,优点是双向通信,服务器与客户端之间交换的数据包头信息很小,缺点就是编码相对来说会多点,服务端处理更复杂。

最终决定采用 webSocket 方案来实现。然而websocket方式也有众多解决方案。

3.4.1 Java Websocket 规范

JavaEE 提供的规范,代码在包javax.websocket下,包含客户端 API 和服务端 API,服务端 API 完全依赖于客户端 API,只是在其基础上添加了一些功能,所以只需要导入服务端依赖即可。

优点:集成起来简单,原生的Java支持。

缺点:和 Web 服务器等共享容器耦合度高,广播、组播需要自行控制。并发量较低,调优麻烦,存在兼容性问题。

3.4.2 Spring Websocket

websocket 已经被springboot很好地集成封装了,所以在springboot上开发 websocket 服务非常方便。

该方案用到了还要用到SockJs+STOMP。

SockJS 是 WebSocket 技术的一种模拟。为了应对许多浏览器不支持WebSocket协议的问题,设计了备选SockJs。开启并使用SockJS后,它会优先选用Websocket协议作为传输协议,如果浏览器不支持Websocket协议,则会在其他方案中,选择一个较好的协议进行通讯。

STOMP是面向消息的简单文本协议。使用STOMP的好处在于,它完全就是一种消息队列模式,你可以使用生产者与消费者的思想来认识它,发送消息的是生产者,接收消息的是消费者。而消费者可以通过订阅不同的destination,来获得不同的推送消息,不需要开发人员去管理这些订阅与推送目的地之前的关系。

优点:性能良好,社区活跃,技术成熟,协议栈丰富,有全套 Spring 解决方案,兼容性强。

缺点:需要对 SockJS 和 STOMP 进行学习,断线重连、心跳检测、二进制支持不好,需要自行实现。

3.4.3 netty Socket.IO

[http://Socket.IO][http_Socket.IO] 基于 Node.js 的实时应用程序框架。虽然主流浏览器都已经支持WebSocket,但仍然可能有不兼容的情况,为了兼容所有浏览器,给程序员提供一致的编程体验。它将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,使用SocketIO时不用担心兼容问题,底层会自动选用最佳的通信方式。而netty-socketio是一个开源的[http://Socket.io][http_Socket.io]服务器端的一个java的实现,它基于Netty框架,同时支持Websocket和长轮询。除了Websocket的常用场景外,可以通过该组件实现安卓和IOS的消息推送。

优点:性能良好,支持广播、组播,断线重连、心跳检测、二进制。支持安卓和 IOS 平台。

缺点:有一定的学习成本,需要自行封装同 Spring 的集成,资源消耗大。

3.4.4 ReactiveStream

一些反应流规范和框架也对Websocket进行了实现。Spring Webflux和RSocket就是其中的代表,目前官方已经放出了一些相关的 DEMO。

优点:高吞吐量、高性能。

缺点:技术比较新、学习资料少,学习成本高。

总结:之前的项目采用spring websocket实现,线上已经平稳运行一段时间。坑也踩的七七八八。决定采用spring websocket技术方案。

4.整体设计

  1. 客户端向消息中心任一节点握手建立起WebSocket长连接,连接session保存在该节点的内存中。此时客户端定时向服务端发送心跳消息,如果超过设定的时间仍没有收到心跳,则认为客户端与服务端的长连接已经断开,然后服务端会关闭连接并清理内存中的会话信息。
  2. 当业务服务需要向客户端推送消息时,调用消息中心提供的api发送到消息中心
  3. 消息中心收到需要推送的请求后,将消息发送到mq
  4. 消息中心作为消费者,以广播模式消费消息,此时所有节点都会消费到消息。
  5. 节点消费消息后判断推送目标对应的session是否保存在自己维护的内存中,如果不存在直接忽略,否则通过长连接推送数据

消息中心目前以双节点方式构成集群,每个节点负责一部分长连接,可以实现负载均衡,当连接数达到瓶颈时,也可以增加节点实现水平扩展。如果某一个节点出现宕机时,客户端通过心跳检测发现后会尝试重新与其他节点建立长连接,保证消息中心服务的可用性。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 背景
  • 2.特性
    • 2.1 分布式
      • 2.2 接入简便
        • 2.3 统一实现
          • 2.4 解耦
            • 2.5 监控
              • 2.6 可靠
                • 2.7 并发
                  • 2.8 性能
                  • 3. 技术调研
                  • 3.1 短轮询
                  • 3.2 长轮询
                  • 3.3 Server-Sent Events
                  • 3.4 WebSocket方案
                    • 3.4.1 Java Websocket 规范
                      • 3.4.2 Spring Websocket
                        • 3.4.3 netty Socket.IO
                          • 3.4.4 ReactiveStream
                          • 4.整体设计
                          相关产品与服务
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档