网页端收消息的 3 种方式(10/31)

轮询拉取、长连接、HTTP 长轮询——实时性与效率怎么兼得

即时通讯架构实践第 10 课封面:即时通讯10:网页端收消息的 3 种方式

轮询拉取、长连接、HTTP 长轮询——实时性与效率怎么兼得

《即时通讯架构核心技术》第 10 篇:网页端收消息的 3 种方式。

场景描述

网页端用户收消息的场景

在网页端登录的用户A,有两类发送给他的消息:

1. 系统发给A的“系统通知”;

2. 用户发给A的“聊天消息”;

系统侧,一般来说,对每一个接收消息的用户都有一个“待收消息”的队列,里面存放了需要给这个用户的所有消息。

用户A,如果是在网页端登录,有几种常见的收取消息的方式呢?

常见的方案有3种。

轮询拉取

轮询拉取

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

1. 网页端起一个timer,每隔一段时间(例如10秒),发起一个轮询请求,拉取队列里的消息;

2. 如果队列里有消息,就返回消息;

3. 如果队列里无消息,就10秒后再次轮询;

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

我最早玩的聊天室,是创办于1996年的互联网老站碧海银沙,大家听过吗?

缺点也很明显:

1. 实时性差:最坏的情况下,1条消息进入队列后,10s之后才会收到;

2. 效率低下:发消息是一个低频动作,如果10次轮询才收到1条消息,请求有效性只有10%,浪费了大量服务器资源;

建立长连接

如果要兼顾实时性和效率,长连接是最佳之选,PC端聊天软件基本都是使用长连接。

网页端常见的实现长连接的方式有两种:

1. WebSocket;

2. FlashSocket;

这两种方案的细节不再展开。

HTTP 长轮询

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

HTTP 长轮询的通知连接

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

1. 这是一条browser发往web-server的HTTP连接;

2. 这条连接只用来收取推送通知;

3. 不像普通的“请求-响应”式HTTP请求,这个HTTP会被服务端夯住,直到有推送通知到达,或者超过约定的时间;

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

场景一:发起通知连接时队列里有消息

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

1. 发起通知连接,正好队列里有消息;

2. 实时把队列里的消息带回;

3. 立马再发起通知连接;

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

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

1. 发起通知连接时,队列里无消息;

2. 一直等待,直到触发“时间阈值”,返回无消息;

3. 立马再发起通知连接;

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

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

1. 新消息来时,正好有通知连接在;

2. 通知连接实时将消息带回;

3. 立马再发起通知连接;

上面三个场景的最终状态,都是“一定,永远,会有一条通知连接,连接在浏览器与服务器之间”,这样就能够保证消息的实时性。

总结

网页端收消息,一般有三种模式:

1. 最容易想到的是拉,但实时性和效率是一对无法调和的矛盾;

2. 最佳的方式是推:

  • WebSocket和FlashSocket是建立TCP长连接
  • 也可以长轮询,通过HTTP短连接拼装长连接,具体是通过“夯住”“只收推送通知”的“通知连接”来实现的,能够做到消息的实时性到达

检验一下

检索练习 · 三种方式
网页端收消息,常见的 3 种方案是?

检索练习 · 轮询的矛盾
10 秒一次的轮询拉取,缺点是什么?

检索练习 · 通知连接
HTTP 长轮询的「通知连接」有什么特点?

检索练习 · 三个场景的最终状态
通知连接在「有消息 / 无消息超时 / 消息恰好到达」三个场景处理完后,最终状态是什么?

网页端用 HTTP 轮询收消息,还能做到「没有延时」?微博网页端就是这么玩的——第 11 篇,HTTP 长轮询为什么没有延时。

知其然,知其所以然。思路比结论更重要。

发表回复

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

京ICP备2025137728号-3