五分钟技术趣谈 | Web端即时通信方案知多少?

网络
随着互联网技术的发展,很多Web应用开始追求用户体验,无需刷新就可以让用户可以实时感知信息的变化,即时通信技术在Web中得到了更广泛的应用。

Part 01

什么是即时通信? 

即时通信是一个实时通信系统,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。即时通信技术在Native App中通过TCP、UDP等协议可以轻松实现,在Native应用较为流行。

受HTTP协议以及Web客户端框架限制,想在Web中实现真正的即时通信,可谓是技术上尽脑汁,极尽所能。从传统的短轮询、长轮询到Comet(长轮询的变体)技术,再到HTML5标准发布之后的WebSocket、 SSE这类技术的横空出现,使Web端即时通信的技术方案越来越多,实现也越来越容易。但是对于技术人员面对不同的场景该如何选择更实用的技术方案呢?

Part 02

Web即时通信实现方案有哪些?

2.1 轮询的原理与实现

轮询分为短轮询与长轮询👇

短轮询:是客户端定期向服务器发起请求查询并获取数据,无论是否有数据服务端都立即响应客户端的请求,该方案较为简单不做过多介绍。

长轮询:是比短轮询更有效的一种技术,当服务器收到浏览器请求后如果有数据, 服务器立刻响应请求; 如果没有数据服务器就会hold一段时间,尽可能长时间的保持浏览器的连接打开;这段时间内如果有数据,服务器立刻响应请求; 如果时间到了还没有数据, 则响应http请求;浏览器收到http响应后,立即再发送一个同样http请求查询是否有数据;如此重复下去。下图是长轮询的交互示意图:

图片

长轮询浏览器代码实现如下:

/* Client - subscribing to the test events */
subscribe: (callback) => {
const pollUserEvents = () => {
$.ajax({
method: 'GET',
url: 'http://localhost:8080/testEvents',
success: (data) => {
callback(data) // process the data
},
complete: () => {
pollUserEvents();
},
timeout: 30000
})
}

2.2 WebSocket的原理与实现

在2008年中期,开发人员Michael Carter和Lan Hickson敏锐的感受到Comet在实现复杂交互时带来的的苦恼和局限,他们制定了一项计划并引入现代实时双向通信的新标准,创造了WebSocket,并进入了W3C HTML草案标准,2011年RFC 6455-WebSocket协议被发布到了IETF网站。

WebSocket是一个构建在设备TCP/IP堆栈上的瘦传输层,一个独立的基于TCP的协议,为Web应用程序开发人员提供尽可能接近原始的TCP通信层,WebSocket与HTTP唯一的关系是它的握手是由HTTP服务器解释为一个Upgrade请求。

图片

WebSocket是一种事件驱动的协议,这意味着可以将其用于真正的实时通信。WebSocket的实现了一次连接,双方多次通信的能力。首先由客户端发出WebSocket连接请求,服务器端进行响应,实现类似TCP握手的动作。这个连接一旦建立起来,在客户端和服务器之间会一直保持该连接,两者之间可以直接的进行数据的互相传送,并且在连接被关闭前可以进行多次交互。

WebSocket浏览器侧代码实现:

const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost/ws');
ws.on('open', function open() {
    ws.send('something');
});
ws.on('message', function incoming(data) {
    console.log(data);
});

WebSocket服务端代码实现:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
    ws.on('message', function incoming(message) {
    console.log('received: %s', message);
    });
    ws.send('something');
});

2.3 SSE的原理与实现

SSE是Server-Sent Events的简称,是一种可以主动从服务端推送消息给浏览器的技术。SSE也是使用HTTP协议进行交互,严格地说HTTP协议无法做到服务器主动推送信息给浏览器,都是浏览器主动去请求服务器端获取最新的数据,SSE技术使服务器与浏览器之间维护一个HTTP长连接,当有新数据时,服务端可以通过这个长连接将数据发送给浏览器。

图片

浏览器主动请求建立一个格式为text/event-stream的stream流 ,服务器给浏览器发送的数据不是一次性的数据包,而是一个stream流,并且浏览器不会关闭连接,会一直等着服务器发送新的数据流报文。

客户端代码实现:

var SSENotification = {
  source: null,
  subscribe: function() {
    if ('EventSource' in window) {
      this.source = new EventSource('/sse');
      this.source.addEventListener('message', function(res) {
        const d = res.data;
        window.ChatroomDOM.renderData(JSON.parse(d));
      });
    }
    return this.unsubscribe;
  },
  unsubscribe: function () {
    this.source && this.source.close();
  }
}

服务器端代码实现:

router.get('/sse', function(req, res) {
  const connectors = chatRoom.getConnectors();
  const messages = chatRoom.getMessages();
  const response = { code: 200, data: { connectors: connectors, messages: messages } };
  res.writeHead(200, {
    "Content-Type":"text/event-stream",
    "Cache-Control":"no-cache",
    "Connection":"keep-alive",
    "Access-Control-Allow-Origin": '*',
  });
  res.write("retry: 10000\n");
  res.write("data: " + JSON.stringify(response) + "\n\n");
  var unsubscribe = Event.subscribe(function() {
    const connectors = chatRoom.getConnectors();
    const messages = chatRoom.getMessages();
    const response = { code: 200, data: { connectors: connectors, messages: messages } };
    res.write("data: " + JSON.stringify(response) + "\n\n");
  });
  req.connection.addListener("close", function () {
    unsubscribe();
  }, false);
});

Part 03

Web即时通信方案对比 

三种即时通信技术方案各有优缺点,三种技术方案特性对比如下:

图片

从对比可以得出👇

长轮询:兼容性好,实现容易;但是由于需要不停向服务器请求查询,很多时候都是无效报文,效率低,客户端数量多时服务端的压力较大;适用于扫码登录,流程状态变化等场景。

WebSocket:支持双向通信,可以实现真正的实时通信,支持二进制数据传输,基本可以胜任各种即时通信场景,而且由于WebSocket的首部信息很小,报文有效载荷高,在海量并发和客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势;但是WebSocket协议相对于HTTP协议较复杂,不支持断线重连,有一定维护成本,因此实际应用中需要基于WebSocket开源SDK进行开发;适用于大型聊天App或大型多人在线游戏的场景。

SSE:属于轻量级方案,主流浏览器都已经支持,使用简单,默认支持断线重连,支持自定义事件类型;但是SSE长连接只支持从服务器向客户端发数据,并且不支持二进制传输(需要编码后传输)。适用于服务器持续向客户端发送数据的场景,如:实时股价流图、在线音视频播放、监视器客户端查看服务器实时信息等。

Part 04

结束语 

轮询、WebSocket、SSE三种技术方案中该如何选择?在消息推送时SSE似乎是我们解决问题的最终选择;但是SSE对于大型游戏、聊天室时又有很多力不从心,不如WebSocket全面;而面对扫码登录等简单场景时轮询似乎更加简单便捷。因此Web端即时通信方案并不能简单的说古老的技术会被新技术替代,项目实施中我们要合理选择,采用更简单、更高效的方案来完成需求。

责任编辑:庞桂玉 来源: 移动Labs
相关推荐

2023-07-02 16:09:57

人工智能人脸识别

2021-09-18 11:36:38

混沌工程云原生故障

2023-07-23 18:47:59

Docker开源

2023-07-16 18:49:42

HTTP网络

2023-04-15 20:25:23

微前端

2023-07-23 08:26:39

平安乡村网络

2023-07-02 16:34:06

GPU虚拟化深度学习

2023-07-30 10:09:36

MMD数据库

2023-07-31 08:55:15

AI技术网络暴力

2023-09-12 07:10:13

Nacos架构

2023-07-12 15:50:29

机器学习人工智能

2023-08-29 06:50:01

Javamaven

2023-08-06 06:55:29

数字可视化物联网

2023-08-15 14:46:03

2023-07-12 16:03:37

Android开发架构

2023-08-06 07:00:59

Openstack网络

2023-09-17 17:51:43

Android 14

2021-06-04 15:38:18

联邦学习人工智能数据

2023-09-02 20:22:42

自动化测试软件开发

2023-07-12 16:13:01

点赞
收藏

51CTO技术栈公众号