HTTP 流和服务器发送的事件有什么区别?

What is the difference between HTTP streaming and server sent events?

我的理解是,HTTP 流式传输涉及客户端发送 HTTP 请求,然后响应随时间发送的请求,从而允许服务器从根本上推送到客户端。在我读到的内容中,SSE 似乎遵循相同的原则运作,但更加正式。接近正确理解了吗?

我看到了这些问题,但他们并没有真正直接回答我的问题。

What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?

我也看了这个https://www.html5rocks.com/en/tutorials/eventsource/basics/#disqus_thread 设置 SSE 的教程,看起来就像我想象的 HTTP 流式传输的设置方式。

SSE 实际上是 HTTP 流的一种形式。它只是一个 MIME 类型为 "text/event-stream" 的 HTTP 响应,它发送以双换行符结尾的纯文本消息。

SSE 不是以前做不到的事情,但是网站必须使用 WebSocket 连接,AJAX 长轮询,彗星,定期轮询等,现在有了 SSE API标准化,实施起来非常简单。参见:

https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

要记住的一件事是 IE(包括 Edge 和 IE Mobile)不支持 SSE:

因此,除非您知道他们使用什么浏览器,否则您还不能真正将它用于更广泛的受众。

恕我直言,HTTP2 服务器发送的事件比 HTTP 流具有丰富的功能。

在可以根据后端事件编排客户端的单向数据流(服务器 -> 客户端)中,服务器发送的事件可能是一个不错的选择。

例如:

# ---------- client side -----------

const eventSource = new EventSource("//your-api/workflow/state");

eventSource.addEventListener("queued", function(event) {
    ...
}
eventSource.addEventListener("started", function(event) {
    ...
}
eventSource.addEventListener("failed", function(event) {
    ...
}
eventSource.addEventListener("success", function(event) {
    ...
}

服务器发送事件的限制:

  • SSE 事件消耗浏览器打开的连接。
  • 最大打开连接数限制不是在浏览器选项卡级别而是在整个浏览器级别
  • 我写的时候,Chrome & Firefox 将它设置为 6(太低了)。此限制是针对每个浏览器 + 域的,因此这意味着您可以在所有选项卡中打开 6 个 SSE 连接到 www.example1.com and another 6 SSE connections to www.example2.com

HTTP 流

有许多 HTTP 流式处理可能有用的用例。如果我们只对来自服务器的消息流感兴趣,这可能很方便。

示例场景:

假设我们想将日志文件内容流式传输到客户端。它可能是一个巨大的文件,或者文件内容不断更新,我们喜欢将它发送给客户端(如日志尾部)。在这种情况下,HTTP 流 (Transfer-Encoding: chunked) 可以满足我们的需求。

# ---------- client side -----------
const streamRequest = (url) => {
    fetch(url).then(function (response) {
        let reader = response.body.getReader();
        let decoder = new TextDecoder();
        return readData();
        function readData() {
            return reader.read().then(function ({value, done}) {
                console.log(value)
                if (value) {
                    let newData = decoder.decode(value, {stream: !done});
                    console.log(newData);    
                }
                if (done) {
                    console.log('end of stream');
                    return;
                }
                return readData();
            });
        }
    });
}

流响应的限制:

  • 在流响应(分块)的情况下 - HTTP/2 不支持 HTTP 1.1 的分块传输编码机制,因为它提供了自己的更高效的数据流机制。