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

简介: 常见的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,并发送消息通知,动态发布者的客户端收到通知后会在浏览动态页右上角显示小红点,提醒用户有未读消息。

相关文章
|
3月前
|
存储 JSON 监控
源码分析Zabbix客户端如何向服务端发起请求
源码分析Zabbix客户端如何向服务端发起请求
30 2
|
4月前
|
网络协议
客户端和服务端交互的基本模型
客户端和服务端交互的基本模型
36 0
|
9月前
|
API
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
Zookeeper学习---2、客户端API操作、客户端向服务端写数据流程
|
9月前
|
网络协议
客户端与服务端交互的基本模型
客户端与服务端交互的基本模型,一定要理解噢!
61 0
EMQ
|
消息中间件 存储 网络性能优化
MQTT 客户端出现连接订阅等问题时如何排查?
这是一期EMQX社区专题FAQ,我们整理了近期社区中关注度较高的问题,在这里进行统一汇总解答。
EMQ
349 0
|
程序员 C#
【C#】SignalR之主动推送信息的简单解决方案
在本篇文章中,将讲讲C#如何使用SignalR通讯 Core下的SignalR实现原理一样,只是写法不一样,主动推送消息的场景使用:页面登录后台管理系统,最新订单信息的通知等
227 0
|
SQL 安全 前端开发
服务端测试
大家好,我是阿萨。前几天我们讲了你了解客户端测试吗?和客户端对应的就是服务器端了。那么服务器端如何测试呢?服务器端相当于一个黑盒子,我们能接触到的只有前台向后端发送的API请求。所以服务器端测试也可以理解为API测试。
202 0
|
存储 前端开发 小程序
springboot集成webstock实战:服务端数据推送数据到客户端实现实时刷新
之前介绍过springboot集成webstock方式,具体参考: springboot集成websocket实战:站内消息实时推送
springboot集成webstock实战:服务端数据推送数据到客户端实现实时刷新
|
运维 Java 数据库连接
排除法,先找客户端问题,再找服务端问题
先找客户端问题,再找服务端问题
56 0
|
消息中间件 RocketMQ 开发者
消息拉取客户端处理服务端相应|学习笔记
快速学习消息拉取客户端处理服务端相应
90 0
消息拉取客户端处理服务端相应|学习笔记