用于双向消息流的 HTTP/2 与 web-sockets

Posted

技术标签:

【中文标题】用于双向消息流的 HTTP/2 与 web-sockets【英文标题】:HTTP/2 vs web-sockets for bidirectional message streaming 【发布时间】:2020-05-09 01:42:00 【问题描述】:

除了不向 javascript 公开 HTTP/2 帧的浏览器之外,在什么情况下,Websockets 会比双向流 gRPC(基于 HTTP/2 构建)等实现实时双向消息流的更好选择?另外,HTTP 2.0 是全双工(和双向)的,不意味着实际上支持服务器推送吗?那么,对 SSE 之类的东西有什么需求呢?这已经过时了,对吧?

【问题讨论】:

【参考方案1】:

这里有很多方面。服务器发送事件,JavaScript Streams API 主要是用于较低级别协议的浏览器 API。

服务器到服务器通信

使用 Websockets 和 HTTP/2 的服务器到服务器通信具有相似的属性。两者都是二进制和高效的协议。 HTTP/2 提供每个流的背压,这对于从多个源接收推送消息或有时可能很忙的客户端来说可能很重要。 gRPC 是 HTTP/2 之上的框架,为开发者提供了更高的抽象。

服务器到浏览器的通信

服务器发送事件

Server Sent Events 是客户端订阅事件流并不断从服务器接收事件的一种方式。 API 是更高的抽象,并且比替代方案更易于使用。但是格式是 text 中指定的消息格式。

开发使用服务器发送事件的 Web 应用程序比使用 websockets 更容易。您需要在服务器上编写一些代码来将事件流式传输到前端,但客户端代码的工作方式几乎与处理任何其他事件相同。

示例代码

const evtSource = new EventSource("/v1/stream/topic");

evtSource.onmessage = function(event) 
   // handle event

JavaScript 流 API

JavaScript Streams API 是一个更新的 JavaScript API,用于支持浏览器和服务器之间的二进制流。这可以与来自Fetch API 的较新的ReadableStream 一起使用。由于这是一个二进制流,它可以有更广泛的用例,并且对于使用例如的应用程序可能很重要。未来几年的网络组装。

API 有点复杂。示例代码:

fetch("https://www.example.org/").then((response) => 
  const reader = response.body.getReader();
  const stream = new ReadableStream(
    start(controller) 
       // implementation
    
  )

二进制流的优点是它可以用于自然二进制数据,例如自定义格式的音频或二进制表示。

在 HTTP/2 或 HTTP/3 Streams 上使用 JavaScript Streams API 的优势在于它支持每个流的背压(不仅是每个 TCP 连接)。

gRPC

gRPC 是一种使用 HTTP/2 流的协议,但它没有在 JavaScript Streams API 上实现,因此对于浏览器通信,它需要一些中间件,例如 grpc-web。

WebSockets

WebSockets 是一个较低级别的抽象,它具有更广泛的浏览器支持,并且支持全双工通信。但由于它是较低级别的抽象,它通常需要库来处理通信。

【讨论】:

对不起,也许是一个愚蠢的问题,但是“背压”是什么意思? ... 我们应该在其中添加 SignalR,作为 WebSockets 之上的常用抽象吗?

以上是关于用于双向消息流的 HTTP/2 与 web-sockets的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 2.0与OkHttp

扩展 gRPC 双向流式聊天服务

面向消息的持久通信与面向流的通信简要总结

HTTP2.0 简介

Redis Stream 流的深度解析与实现高级消息队列一万字

Redis Stream 流的深度解析与实现高级消息队列一万字