如何实现服务端向客户端推送数据

简介: 常见的http协议只能从客户端主动向服务端请求数据,而服务端无法向客户端发送数据.本文通过介绍几种方式来实现上述功能.

以微信朋友圈为例:
朋友圈提供动态点赞与评论功能,我们需要一种机制或方法保证用户在使用朋友圈过程中能相对实时地收到其他用户的点赞和评论消息。简单来说,就是实现双向通信。常用的Http协议通信只能由客户端发起,服务端接收到请求并做出应答,显得十分被动,这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。

经过调研,找到以下几种实现双向通信的方式:

1.轮询(polling):让客户端隔个几秒就发送一次请求,询问服务器是否有新信息。

用大白话举例就是:

while True: 客户端:妹子,请你吃饭有空吗?(Request)

服务端:没有!(Response)

客户端:妹子,请你吃饭有空吗?(Request)

服务端:没有。。(Response)

客户端:妹子,请你吃饭有空吗?(Request)

服务端:你好烦啊,没有啊。。(Response)

客户端:妹子,请你吃饭有空吗?(Request)

服务端:好啦好啦,有啦。(Response)

客户端:妹子,请你吃饭有空吗?(Request)

服务端:。。。。。没。。。。没。。。没有(Response)

  • 优点:实现简单,无需做过多的更改
  • 缺点:轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担

2.长轮询(long-polling):长轮询其实原理跟轮询差不多,都是采用轮询的方式,不过采取的是阻塞模型,也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。

还是用大白话举例:

while True:

客户端:妹子,请你吃饭有空吗?没有的话就等有了再返回给我吧!(Request)

服务端:(额。。现在好忙,先不回复他,电话先不挂。)

服务端:现在有空了。(Response)

客户端:妹子,请你吃饭有空吗?没有的话就等有了再返回给我吧!(Request)

服务端:(额。。现在好忙,先不回复他,电话先不挂。)

服务端:现在有空了。(Response)

  • 优点:比 polling 做了优化,有较好的时效性
  • 缺点:保持连接会消耗资源;服务器没有返回有效数据,程序超时

3.iframe流(streaming):iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据,来实时更新页面。

while True:

客户端:妹子,请你吃饭有空吗?(Request)

服务端:您好,您所拨打的用户正在通话中,请稍后再拨。(503 Server Unavailable)

客户端:妹子,请你吃饭有空吗?(Request)

服务端:您好,您所拨打的用户正在通话中,请稍后再拨。(503 Server Unavailable) 服务端忙的要死:(我要更多的资源,资源。。。)

  • 优点:消息能够实时到达;浏览器兼容好
  • 缺点:服务器维护一个长连接会增加开销;IE、chrome、Firefox会显示加载没有完成,图标会不停旋转。

经过个人的评估,得出了最优解

WebSocket,它是基于TCP/IP协议,独立于HTTP协议的通信协议,而且能实现客户端与服务端双向实时响应(客户端 ⇄ 服务端)。
客户端:我要建立WebSocket协议,需要的服务:chat,WebSocket协议版本:17(HTTP Request)

服务端:ok,确认,已升级为WebSocket协议(HTTP Protocols Switched)

客户端:你有事的时候记得要找我噢!

服务端:ok,有事的时候会找你的。 服务端:我想吃炸鸡了。 服务端:我想喝奶茶了。 服务端:我不开心了。

服务端:balabalabalabala。。。

选择原因:

  • 支持双向通信,实时性更强
  • 可以发送文本,也可以发送二进制数据
  • 减少通信量:只要建立起WebSocket连接,就希望一直保持连接状态。和HTTP相比,不但每次连接时的总开销减少,而且由于WebSocket的首部信息很小,通信量也相应减少了。
  • 方便与springboot集成,降低开发成本

相对于传统的HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似Socket的TCP长连接的通讯模式,一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端断掉连接前,不需要客户端和服务端重新发起连接请求。 在海量并发和客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

具体的技术实现如下(模拟朋友圈):
当用户进入朋友圈,前端监听到对应事件,带上当前用户的token开始与服务端建立websocket连接,服务端接收到请求,解析请求的token,获取到该用户的openId,把它作为key,缓存当前连接的session()。当其他用户对该用户的动态点赞或评论,服务端接收到请求并执行完相关的逻辑后会查找session缓存中是否存在该动态发布者的session,若存在(该用户在线),则找到该session,并发送消息通知,动态发布者的客户端收到通知后会在浏览动态页右上角显示小红点,提醒用户有未读消息。

相关文章
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
|
6月前
|
存储 JSON 监控
源码分析Zabbix客户端如何向服务端发起请求
源码分析Zabbix客户端如何向服务端发起请求
72 2
|
6月前
|
网络协议
客户端和服务端交互的基本模型
客户端和服务端交互的基本模型
55 0
|
11月前
|
网络协议 Cloud Native
为什么服务端会有那么多的 TimeWait ?
为什么服务端会有那么多的 TimeWait ?
|
网络协议
客户端与服务端交互的基本模型
客户端与服务端交互的基本模型,一定要理解噢!
90 0
|
Java 开发者
JavaHTTP心跳:服务器与客户端实时连接的实现方式
JavaHTTP心跳:服务器与客户端实时连接的实现方式 在网络通信中,实时连接是一种至关重要的功能。它允许服务器与客户端之间保持持久的通信信道,实现快速、高效的数据传输。对于Java开发者来说,实现服务器与客户端之间的实时连接可以通过JavaHTTP心跳技术来实现。本文将介绍如何利用JavaHTTP心跳来实现服务器与客户端之间的实时连接。
340 0
|
Web App开发 移动开发 前端开发
还在用轮询吗,SSE服务端推送实现页面实时更新
最近开发一个页面碰到一个需求,需要对部分数据需要实时更新状态
416 0
|
存储 前端开发 小程序
springboot集成webstock实战:服务端数据推送数据到客户端实现实时刷新
之前介绍过springboot集成webstock方式,具体参考: springboot集成websocket实战:站内消息实时推送
springboot集成webstock实战:服务端数据推送数据到客户端实现实时刷新
|
消息中间件 RocketMQ 开发者
消息拉取客户端处理服务端相应|学习笔记
快速学习消息拉取客户端处理服务端相应
消息拉取客户端处理服务端相应|学习笔记
|
消息中间件 缓存 RocketMQ
客户端发起拉取消息请求|学习笔记
快速学习客户端发起拉取消息请求
客户端发起拉取消息请求|学习笔记
下一篇
无影云桌面