专栏首页架构师之路网页端收消息,究竟是推还是拉?

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

任何脱离业务的架构设计都是耍流氓。网页端收消息,究竟是推还是拉?

需求缘起

对于在网页端登录的用户A,发送方,也就是消息的来源有几方面:

  • 系统发给A的“系统通知”,可能对实时性要求没这么高
  • 用户发给A的“聊天消息”,有对实时性要求比较高,越实时越好

消息的处理方,也就是系统侧,一般来说:

  • 有服务对消息进行逻辑处理
  • 有数据库对数据进行落地
  • 有缓存对数据进行加速

抛开这些技术细节不谈,暂且认为服务端对每一个用户都有一个“待收消息”的队列,里面存放了需要给这个用户的一切消息。

消息的接收方,也就是用户A,如果是在网页端登录,因为HTTP协议是“请求-响应”式的,服务端与网页之间没有消息通道,对于这类“收消息”的需求,是如何处理的呢?

方案一、轮询拉取

轮询拉取,是最容易想到的实现方式:

  • 发送方发送了消息,先入队列
  • 网页端起一个timer,每个一段时间(例如10秒),发起一个轮询请求,拉取队列里的消息
  • 如果队列里有消息,就返回消息
  • 如果队列里无消息,就10秒后再次轮询

这种方式的优势是:实现简单,直观且,容易理解,互联网兴起时,人数不多的聊天室就是这么玩的。

画外音:创办于1996年的互联网老站碧海银沙,曾经中国最火爆的聊天室,已于2017.9.27停止运营。

缺点也很明显:

  • 实时性差:最坏的情况下,1条消息进入队列后,10s之后才会收到
  • 效率低下:发消息是一个低频动作,如果10次轮询才收到1条消息,请求有效性只有10%,浪费了大量服务器资源

更要命的是,在这种方案下,实时性与效率是一对不可调和的矛盾:如果将轮询周期设为1/10,将时延缩短到1秒,意味着100次轮询才会收到1条消息,请求有效性则降为了1%。

方案二、建立长连接

如果要兼顾实时性和效率,长连接是最佳之选,PC端聊天软件基本都是使用长连接。网页端常见的实现长连接的方式有两种:

  • WebSocket
  • FlashSocket

这两种方案的细节不再展开,ta们均有一定的局限性。

更为通用的方式,是“长轮询”。

长轮询,是通过拼装HTTP短连接来达到长连接的效果,即保证了消息100%实时,又最大化的系统效率。

方案三、HTTP长轮询

HTTP长轮询的核心在于,浏览器与服务端之间建立了一条“通知连接”,它的特点是:

  • 这是一条browser发往web-server的HTTP连接
  • 这条连接只用来收取推送通知
  • 不像普通的“请求-响应”式HTTP请求,这个HTTP会被服务端夯住,直到有推送通知到达,或者超过约定的时间

画外音:对于HTTP请求,为了提高效率,一般来说browser和web-server都会有一些设置,如果一条HTTP请求长时间没有数据(例如,150秒),会被断开。“通知连接”为了不被browser和web-server粗暴断开,一般会设置一个约定阈值(例如,小于150秒),由系统返回一个空消息,以便“优雅返回”。

更具体的,对于这条“夯住”与“只收推送通知”的“通知连接”,是怎么玩的呢?

场景1,发起通知连接时,队列里正好消息,则:

  • 发起通知连接,正好队列里有消息
  • 实时把队列里的消息带回
  • 立马再发起通知连接

场景二,发起通知连接时,队列里消息,则:

  • 发起通知连接时,队列里无消息
  • 一直等待,直到触发“时间阈值”,返回无消息
  • 立马再发起通知连接

场景三,新消息来时,正好通知连接在,则:

  • 新消息来时,正好有通知连接在
  • 通知连接实时将消息带回
  • 立马再发起通知连接

上面三个场景的最终状态,都是“一定,永远,会有一条通知连接,连接在浏览器与服务器之间”,这样就能够保证消息的实时性。当然,有人会说,HTTP的返回与再次发起会有一个时间差,如果这个时间差,恰巧有新消息过来呢?

场景四,新消息来时,没有通知连接,则:

  • 新消息来时,没有通知连接
  • 把新消息放入队列

最后这个场景,发生的概率非常小,但也确保了在“HTTP的返回与再次发起会有一个时间差”内,消息不会丢失,在通知连接发起后,消息能够实时返回。

总结

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

  • 最容易想到的是,但实时性和效率是一对无法调和的矛盾
  • 最佳的方式是,但WebSocket和FlashSocket各有局限性
  • 最通用的方式是长轮询,通过HTTP短连接拼装长连接,具体是通过“夯住”“只收推送通知”的“通知连接”来实现的,能够做到消息的实时性到达

本文分享自微信公众号 - 架构师之路(road5858),作者:58沈剑

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 缓存与数据库不一致,咋办?

    缓存与数据库的操作时序,不管是《Cache Aside Pattern》中的方案,还是《究竟先操作缓存,还是数据库?》中的方案,都会遇到缓存与数据库不一致的问题...

    架构师之路
  • 缓存,你真的用对了么?

    缓存,是互联网分层架构中,非常重要的一个部分,通常用它来降低数据库压力,提升系统整体性能,缩短访问时间。

    架构师之路
  • 不敢相信,技术栈,居然被P站秒了

    PornHub的FE,分享了P站前端一些实践,英文比较晦涩难懂,故翻译整理了一下,很多同学对前端技术不是很熟悉,故加入了简单解释,希望对大家理解相关技术有帮助。...

    架构师之路
  • Yahoo! 十三条 : 前端网页优化(13+1)条原则

      据统计,有80%的最终用户响应时间是花在前端程序上,而其大部分时间则花在各种页面元素,如图像、样式表、脚本和Flash等的下载上,减少页面元素将会减少HTT...

    csxiaoyao
  • Mac安装软件提示 已损坏【已解决】

    从网上下载的SecureCRT、Principle等设计软件,以及输入法等常用软件,安装时可能会提示“已损坏,移至废纸篓”这类信息,根本无法打开。如下图: 这...

    斑马
  • 既然有 HTTP 请求,为什么还要用 RPC 调用?

    HTTP协议,以其中的Restful规范为代表,其优势很大。它可读性好,且可以得到防火墙的支持、跨语言的支持。而且,在去年的报告中,Restful大有超过RPC...

    week
  • 【答疑解惑】Java类的加载顺序

    语音版: Java类的初始化顺序这个问题经常出现在面试题中,这个面试题设计的知识有类、对象、static关键字、初始化函数、类的加载顺序,咱们一个一个来说。 类...

    程序员互动联盟
  • 秒懂!四步16点高效搞定高性能web服务器nginx

    Nginx(读音engine x)服务器由于性能优秀稳定、配置简单以及跨平台,被越来越多的公司和个人所采用,现已成为市场份额继Apache之后的第二大Web服务...

    小小科
  • FPGA基础知识极简教程(3)从FIFO设计讲起之同步FIFO篇

    缩写FIFO代表 First In First Out。FIFO在FPGA和ASIC设计中无处不在,它们是基本的构建模块之一。而且它们非常方便!FIFO可用于以...

    Reborn Lee
  • CEVA 蓝牙和语音产品解决方案

    以下为CEVA蓝牙,特别是低功耗蓝牙,以及面向语音应用的DSP和软件综合解决方案。

    用户6026865

扫码关注云+社区

领取腾讯云代金券