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

28
我的理解是HTTP流媒体涉及客户端发送HTTP请求,然后响应请求随时间发送,使得服务器基本上可以向客户端推送。从我所读的内容来看,SSE遵循相同的原则,但更加正式化。这个理解是否正确?我看到了这些问题,但它们没有直接回答我的问题。 HTTP:管道、保持活动和服务器发送事件之间的关系是什么? 什么是长轮询、Websockets、服务器发送事件(SSE)和彗星? 我还查看了这个 https://www.html5rocks.com/en/tutorials/eventsource/basics/#disqus_thread 用于设置SSE的教程,它似乎就像我想象中设置HTTP流媒体一样。
2个回答

27

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

SSE并不是以前无法实现的东西,但网站必须使用WebSocket连接、AJAX长轮询、Comet、周期性轮询等方法,现在通过SSE,API被标准化且实现非常简单。详见:

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

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

因此,除非您知道用户使用的浏览器,否则不能真正将其用于更广泛的受众群体(尚未)。


1
不确定为什么你被投票否决了,那听起来对我很好。谢谢! - Bren
3
那么最终,实际上有什么区别呢?这个问题没有回答。如果两者相同(除了您提到的MIME类型标头),那么即使我们已经有了HTTP流式传输,引入SSE的意义何在?我觉得这个问题还有更多的内容。 - theprogrammer
@theprogrammer 这是对之前“松散定义”的标准化。它还引入了更容易处理此问题的浏览器API。 - Evert
2
MDN表示:“当未在HTTP/2上使用时,SSE受到打开连接的最大数量限制,这可能在打开多个选项卡时特别痛苦,因为限制是每个浏览器设置为非常低的数字(6)。”截至2020年,您对此有何看法?这个限制仍然存在吗?如果是,则我们首先不应该使用这种技术,而应该选择像WebSocket连接之类的东西。您怎么看?谢谢! - tonix
@tonix 当使用 SSE 而非 HTTP/2 时,多个标签页仍存在限制(6)。 - Wrapper

8

在我看来,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) {
    ...
}

Server sent events 的限制:

  • SSE事件消耗浏览器打开的连接。
  • 在整个浏览器范围内有最大打开连接数限制,而不是在浏览器选项卡级别上。
  • 截至我编写此文时,Chrome和Firefox将其设置为6(太低了)。此限制是每个浏览器 + 域名的限制,这意味着您可以在所有标签中打开6个与www.example1.com相关的SSE连接,以及另外6个与www.example2.com相关的SSE连接。

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的分块传输编码机制,因为它提供了自己更高效的数据流传输机制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接