Java八股文系列
# Java八股文系列
# 消息推送
我相信大家都遇到过,在刷短视频的时候,如果别人点赞或者评论,你的视频系统它会实时的给你推送一条动态信息,你不需要重新的进入系统是能够实时感知到的。又或者我们在进行在线聊天的时候,我们需要实时感知到对方发送的信息。或者我们在进行多人的在线游戏的时候,当别人出了什么牌或者释放了什么技能,我们也需要实时的能够感知。甚至我们在线下使用的一些共享设备。当我们在手机上面点击开锁,此时共享单车它会收到一条实时推送的开锁指令,进而给单车进行开锁。
所以说在我们的应用当中和生活当中,是会涉及到非常多这些实时消息推送的一些场景的那这些功能又是如何实现的呢?下面就来给大家介绍几种常见的消息推送的实现。
# 轮询
# 短轮询
首先第一种是轮询,轮询又分短轮询和长轮询。我们现在来介绍一下短轮询。短轮询很简单,说白了就是在前端的写一个定时任务。比如说每隔一秒向服务端发起一个ajax请求,服务端进行响应,以此进行不断的轮询下去。
短轮询它的弊端,其实你会发现,可能100次请求当中,只有十次请求才是数据发生了变化。另外的这99次,有可能都是数据没有发生变化。所以对服务器来说,毫无疑问会造成资源的一个浪。如果说请求量非常大的一个情况下,服务器势必会承受非常大的一个压力。
# 长轮询
那利用长轮询就可以减少一些无效的请求次数。同样的当前端发起一个请求获取最新的消息,后端它不会立马响应,而是将当前的请求线程进行挂起。只有出现了最新的消息才会响应给前端,以此进行轮询。在这个过程当中,你会发现请求次数确实变少。因为只有当后端发现了数据发生了改变,它才会进行响应。但是在这个过程当中,请求的线程需要一直挂载进行等待。这里就会出现两个问题。
第一个问题就是如果等待的时间过长,一直都没有数据改变,那么前端肯定会发生请求超时。为了这个情况,其实可以给前端的响应一条空数据。当前端处理这个空数据的响应时,再一次的去服务器发起一个请求,所以说这个问题也不是非常难处理。
最大的问题是什么呢?依然是在请求量大的情况下,服务器的线程会发生线程的一个堆积,从而对服务器造成非常大的一个压力。
所以不管是短轮询或者是长轮询,虽然实现起来非常的简单,但是他们也只能去应对一些简单的业务场景,以及请求量低的情况比较适用。如果是在请求量高的一些并发场景,那么轮询的方式肯定是不推荐进行使用的.
那有没有什么方式能够减少轮询当中这种频繁请求响应的次数呢?只有当发生了数据才主动给前端去推送消息。
# SSE方式
SSE是Server-Sent Events的缩写,是一种由服务器向浏览器发送实时更新的技术。SSE允许服务器主动推送数据到客户端,而不是客户端定期向服务器请求数据。使用SSE可以实现例如实时聊天、通知、直播更新等应用场景。
这种方式同样的需要前端先主动的发起一个请求到后端。后端会在响应当中进行sse长链接的一个协议。此时客户端收到长链接协议会跟服务端建立一个连接。
建立连接之后,服务端一旦发生了数据的改变,可以实时的往客户端去推送消息。但是这种方式它是单向通道,也就是在长链接建立完之后,是允许服务端向客户端实时推送消息
。而客户端无法向服务端是推送消息。所以SSSSE它比较适用于只需要服务端向客户端进行数据推送的场景,比如说股票、天气预报等等。并且使用sse不需要依赖任何其他第三方的组件,因为它是HTP协议本身就自带的功能
。
# websocket
如果要改变单向通道的问题,我们可以采用websocket。同样的需要通过客户端发起一个长链接的请求。那么服务端需要进行同意,同意之后,他们之间会进行一个双向通道的连接。此时他们就可以进行双向的消息实时通信,
Websocket也是我们现在开发复杂业务下的消实时通讯普遍使用的一种技术。当然我们通常会基于netty框架来进行开发实时通信业务以及并发量高的复杂场景。因为netty它帮我们集成了模型,以及对web socket进行了封装,使得我们使用socket更加的方便,性能也更加的高。现在很多招java游戏后端的岗位,基本要求的也都是需要有netty。
# MQTT
最后我再来给大家介绍一种叫做MQTT。MQTT它主要是针对我们物联网。因为在物联网的场景下,往往会出现设备的网络不稳定,无法像我们的HTTP请求一样实时的请求响应。并且像这种设备,他们所需要传输的数据不宜太大。那MQTT毫无疑问是最适用的。
MQTT可以采用rabbit MQ来进行实现,它其实跟我们的订阅发布模型是一致的。所有的设备通过MQ代理进行订阅,并且也可以进行发布。所以MQTT同样也是双向的通道。任意一个设备都可以往MQTTT代理当中去发布一个消息。另外在所有的设备是能够实时感知得到的。并且MQTT它还提供了三个保证消息传递可靠性的级别,以保证消息在传递时的可靠性。