任何脱离业务的架构设计都是耍流氓 。网页端收消息,究竟是推还是拉?
需求缘起
文章插图
对于在网页端登录的用户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
更为通用的方式,是“长轮询” 。
长轮询,是通过拼装HTTP短连接来达到长连接的效果,即保证了消息100%实时,又最大化的系统效率 。
方案三、HTTP长轮询
文章插图
HTTP长轮询的核心在于,浏览器与服务端之间建立了一条“通知连接”,它的特点是:
- 这是一条browser发往web-server的HTTP连接
- 这条连接只用来收取推送通知
- 不像普通的“请求-响应”式HTTP请求,这个HTTP会被服务端夯住,直到有推送通知到达,或者超过约定的时间
更具体的,对于这条“夯住”与“只收推送通知”的“通知连接”,是怎么玩的呢?
文章插图
场景1,发起通知连接时,队列里正好有消息,则:
- 发起通知连接,正好队列里有消息
- 实时把队列里的消息带回
- 立马再发起通知连接
文章插图
场景二,发起通知连接时,队列里无消息,则:
- 发起通知连接时,队列里无消息
- 一直等待,直到触发“时间阈值”,返回无消息
- 立马再发起通知连接
文章插图
推荐阅读
- 教师|终于等到你,教师行业或将实行“工龄退休”,好消息一波接一波
- 淘宝只卖5元的Win10靠谱吗?
- 三星|硬上革命性技术结果翻车:消息称三星3nm工艺无法如期量产
- 下个月起正式实施,机动车迎来5个好消息
- iPhone|赶快囤了?消息称苹果今年9月行动:欲放弃一代神机iPhone 11全系
- 再见HTML ! 用纯Python就能写一个漂亮的网页
- 教育部|教育部下发好消息,“第一学历”迎来变动,专科生不再受限制!
- 网页怎么搜索关键词 淘宝关键词搜索技巧
- 手淘消息中心是什么流量 手淘推荐的流量是哪里来的
- 浅谈浏览器架构、单线程js、事件循环、消息队列、宏任务和微任务