LabHub
学习 学习路径 课程

SSE — 服务端先说话的方式

SSE 比 WebSocket 更合适的场合更多的原因

在 LabHub 中继续学习

一句话总结

SSE是没有结束的HTTP响应。因为不是新协议,所以代理、认证、重新连接、日志记录全部保持原样运行。

流程图: 没有结束的HTTP响应 · 浏览器自动 · 内置 · 如果客户端不需要继续向服务器说话,SSE几乎总是正确的。

有什么不同

SSE WebSocket
协议 只是HTTP Upgrade后单独
方向 服务器 → 客户端 双向
重新连接 浏览器自动 直接实现
继续追赶错过的东西 Last-Event-ID内置 直接实现
认证 保持Cookie·头像不变 必须放在握手处
代理/LB 保持原样 需要单独设置
数据 文本(UTF-8) 文本 + 二进制

**如果客户端不需要继续向服务器说话,SSE几乎总是正确的。**通知、进度、仪表板更新,以及LLM令牌流都是如此。用户的输入是普通的POST发送到就可以了。

电线格式

Content-Type: text/event-stream于是,本文就这样出现了。

event: token
id: 42
data: 안녕

data: 여러 줄이면
data: data: 를 반복한다

: 이건 주석이다. 하트비트로 쓴다

retry: 3000

规则五行就结束了。

浏览器那一边有三行

const es = new EventSource("/stream")
es.addEventListener("token", e => append(e.data))
es.onerror = () => { /* 브라우저가 알아서 다시 붙는다 */ }

断开连接后**会自动重新连接,最后收到的idLast-Event-ID放在头中发送。**如果服务器从那个id之后开始发送的话,用户也不会知道断开连接。要用WebSocket做同样的事情,必须亲自制作重新连接、去重、保证顺序。

所以为什么不行——缓冲

在SSE中实际经历的问题大部分都是一样的。

密码对了,但是画面上一次性出现。

中间有人正在收集回应。犯人有三个人。

**1. 反向代理。**nginx默认缓存响应。

proxy_buffering off;              # location 에

或者在应用程序中用头条连接——X-Accel-Buffering: no.

2.压缩。 gzip 需要以块为单位合并才能压缩。Content-Encoding: gzip如果加上这个,流媒体实际上就会死掉。SSE响应在压缩中被排除在外。

3.框架。 误认为创建响应并一次性返回的代码是流式传输的情况。将生成器yield不做,做一份清单然后还给我,就只是一个很大的回应。

诊断是按时间进行的。curl -N附着在上面看看第一个字节什么时候来。如果全部制作完成后才来的话,就是在收集什么东西。-N是关闭curl自己缓冲器的选项。

没有心跳就会断开

路由平衡器·代理有闲置超时(一般60秒)。如果没有任何数据流,就会断开连接。所以定期流出一行注释。

: ping

**客户不把这个看作是活动。**只流过字节。15~30秒的间隔就足够了。

连接次数限制

在HTTP/1.1中,浏览器限制为每个原生端同时连接6个。一个SSE会永久占用其中一个。打开六个标签,第七个标签的请求都会停止。**使用HTTP/2就会消失的问题(多路复用)。如果在生产中使用SSE,HTTP/2不是选择。

服务器方面忘记的事情

即使客户端断开连接,发电机也会继续运转——如果没有注意并停止的话。每次用户关闭标签,服务器都会有一项僵尸任务累积起来。

async def gen():
    try:
        while True:
            yield {...}
    finally:
        await cleanup()      # 끊길 때 반드시 여기로 온다

finally粘贴应该成为习惯。

现场诊断的顺序

如果收到“代码正确,但画面一次性出现”的举报,在修改服务器代码之前,先切断流到哪里

  1. curl -N http://앱주소/stream—直接粘在应用程序上。-N是关闭curl自己输出缓冲区的选项。如果删除这个,可能会因为工具而怀疑服务器。
  2. 通过代理再次发送同样的请求。如果只在这里聚集,犯人就会出现缓冲或压缩。
  3. 浏览器开发者工具Network选项卡的EventStream——事件是否一个一个地到达

一步一步缩小范围,几分钟内就能确定服务器、代理、客户端中需要修理哪一个。在诊断时,首先怀疑的是测量工具本身

什么时候是WebSocket呢

除此之外,SSE的运营要便宜得多。以连接中断时什么会自动恢复为标准选择的话,一般都会得到答案。