网页端收消息,究竟是推还是拉?

任何脱离业务的架构设计都是耍流氓。
 
网页端收消息,究竟是推还是拉?
 
什么业务场景?
网页端收消息,究竟是推还是拉?
对于在网页端登录的用户A,发送方,也就是消息的来源有几方面:
(1)系统发给A的“系统通知”,可能对实时性要求没这么高;
(2)用户发给A的“聊天消息”,有对实时性要求比较高,越实时越好;
 
消息的处理方,也就是系统侧,一般来说:
(1)有服务对消息进行逻辑处理;
(2)有数据库对数据进行落地;
(3)有缓存对数据进行加速;
抛开这些技术细节不谈,暂且认为服务端对每一个用户都有一个“待收消息”的队列,里面存放了需要给这个用户的一切消息。
 
消息的接收方,也就是用户A,如果是在网页端登录,因为HTTP协议是“请求-响应”式的,服务端与网页之间没有消息通道,对于这类“收消息”的需求,是如何处理的呢?
 
方案一:轮询拉取
网页端收消息,究竟是推还是拉?
轮询拉取,是最容易想到的实现方式:
(1)发送方发送了消息,先入队列;
(2)网页端起一个timer,每个一段时间(例如10秒),发起一个轮询请求,拉取队列里的消息;
(3)如果队列里有消息,就返回消息;
(4)如果队列里无消息,就10秒后再次轮询;
 
这种方式的优势是:实现简单,直观且,容易理解互联网兴起时,人数不多的聊天室就是这么玩的。
画外音:创办于1996年的互联网老站碧海银沙,曾经中国最火爆的聊天室,已于2017.9.27停止运营
 
缺点也很明显:
(1)实时性差:最坏的情况下,1条消息进入队列后,10s之后才会收到;
(2)效率低下:发消息是一个低频动作,如果10次轮询才收到1条消息,请求有效性只有10%,浪费了大量服务器资源;
 
更要命的是,在这种方案下,实时性与效率是一对不可调和的矛盾:如果将轮询周期设为1/10,将时延缩短到1秒,意味着100次轮询才会收到1条消息,请求有效性则降为了1%。
 
方案二:建立长连接
如果要兼顾实时性和效率,长连接是最佳之选,PC端聊天软件基本都是使用长连接。网页端常见的实现长连接的方式有两种:
(1)WebSocket;
(2)FlashSocket;
这两种方案的细节不再展开,ta们均有一定的局限性。
 
更为通用的方式,是“长轮询”
长轮询,是通过拼装HTTP短连接来达到长连接的效果,即保证了消息100%实时,又最大化的系统效率。
 
方案三:HTTP长轮询
网页端收消息,究竟是推还是拉?
HTTP长轮询的核心在于,浏览器与服务端之间建立了一条“通知连接”,它的特点是:
(1)这是一条browser发往web-server的HTTP连接;
(2)这条连接只用来收取推送通知;
(3)不像普通的“请求-响应”式HTTP请求,这个HTTP会被服务端夯住,直到有推送通知到达,或者超过约定的时间;
画外音:对于HTTP请求,为了提高效率,一般来说browser和web-server都会有一些设置,如果一条HTTP请求长时间没有数据(例如,150秒),会被断开。“通知连接”为了不被browser和web-server粗暴断开,一般会设置一个约定阈值(例如,小于150秒),由系统返回一个空消息,以便“优雅返回”。
 
更具体的,对于这条“夯住”与“只收推送通知”的“通知连接”,是怎么玩的呢?
 
网页端收消息,究竟是推还是拉?
场景1,发起通知连接时,队列里正好消息,则:
(1)发起通知连接,正好队列里有消息;
(2)实时把队列里的消息带回;
(3)立马再发起通知连接;
网页端收消息,究竟是推还是拉?
场景二,发起通知连接时,队列里消息,则:
(1)发起通知连接时,队列里无消息;
(2)一直等待,直到触发“时间阈值”,返回无消息;
(3)立马再发起通知连接;
网页端收消息,究竟是推还是拉?
场景三,新消息来时,正好通知连接在,则:
(1)新消息来时,正好有通知连接在;
(2)通知连接实时将消息带回;
(3)立马再发起通知连接;
 
上面三个场景的最终状态,都是“一定,永远,会有一条通知连接,连接在浏览器与服务器之间”,这样就能够保证消息的实时性。当然,有人会说,HTTP的返回与再次发起会有一个时间差,如果这个时间差,恰巧有新消息过来呢?
网页端收消息,究竟是推还是拉?
场景四,新消息来时,没有通知连接,则:
(1)新消息来时,没有通知连接;
(2)把新消息放入队列;
 
最后这个场景,发生的概率非常小,但也确保了在“HTTP的返回与再次发起会有一个时间差”内,消息不会丢失,在通知连接发起后,消息能够实时返回。
 
总结
网页端收消息,究竟是推还是拉?
(1)最容易想到的是,但实时性和效率是一对无法调和的矛盾;
(2)最佳的方式是,但WebSocket和FlashSocket各有局限性;
(3)最通用的方式是长轮询,通过HTTP短连接拼装长连接,具体是通过“夯住”“只收推送通知”的“通知连接”来实现的,能够做到消息的实时性到达;

发布者:糖太宗,转载请注明出处:https://www.qztxs.com/archives/science/technology/6793

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年5月15日 下午9:22
下一篇 2022年5月15日 下午9:23

相关推荐

  • 洞态IAST 钉钉自动化告警闭环

    前言 洞态IAST上线有一段时间了,基于被动式IAST技术,高检出率和低误报率等特点,很好的集成到devops流程中,增加我们的效率,然而每次发现漏洞后没有及时查看导致漏洞处理上的滞后,这里通过钉钉群里机器人做自动化告警,使IAST使用上闭环起来   钉钉群聊机器人(这里可以使用飞书、企业微信等都可以的) 群里机器人文档:https://devel...

    2022年6月12日
    7500
  • PHP编程基础学习记录

    印象笔记中躺着一篇当时学PHP的一篇笔记,贴出来,从慕课网上学的 PHP官方手册 看代码还是直接查手册吧   PHP 运行在服务端、跨平台、脚本语言、免费 代码标识 1 2 3 1 2 3 4 5 6 7 8 9 10 11 例子: A想要从自己的帐户中转1000块钱到B的帐户里。那个从A开始转帐,到转帐结束的这一个过程,称之为一个事务。在这个事务...

    技术 2022年6月13日
    3500
  • 某手v8.x版本抓包分析

    快手升级到v8.x版本以后,会发现直接用Charles、Fiddler等抓包工具抓包的时候,抓不到包了。这是因为快手用了quic协议,下面就具体讲一下分析过程和解决方案。 一、分析过程 我曾经在分析sig参数的时候看到过有一个方法入参是okhttp3.Request,我们就直接从这里入手。 用Frida hook一下,打印request看一下。 var s ...

    2022年6月2日
    7200
  • 面试杀手锏:Redis源码之SDS(Redis 数据结构源码解析)

    1.前言 Hello,欢迎大家来到《 Redis 数据结构源码解析系列》,在《Redis为什么这么快?Redis底层实现原理》一文中我说过 ,Redis 速度快的一个原因就是其简单且高效的数据结构。(新手建议反复多推敲几遍) 2.SDS命令实战[初来乍到] SDS 是 Redis 中最简单的数据结构。Redis 中所有的数据结构都是以唯一的 key 字符串作...

    2022年5月19日
    3100
  • 应用系统安全通用技术要求(转发)

    转发自 https://github.com/aka99/sdl/blob/master/appsecreq.md 1 标识与鉴别 1.1 身份标识 应用系统的管理员及普通用户应具有明确的身份标识(账号):   a) 身份标识应具有唯一性,保证应用系统中不存在重复身份标识; b) 身份标识应不可预测,如递增的序列号等; c) 将身份标识与审计记录关...

    技术 2022年5月27日
    6500

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信