Skip to content
FunCoding

Search

Search docs, Skills and MCP

SSE 背压与慢客户端

区分帧数、字节、重放预算和 MCP App 文本降级。

This page has not been translated into English yet. The original Chinese version is shown below.

EventBus 为每个 session 保留 ring,为每个 subscriber 维护独立 live queue。一个客户端消费慢,不应使其他客户端或 agent 执行无限等待。

默认限制

项目默认或范围
每 session subscriber64
每 subscriber live backlog256 帧
每 subscriber live bytes2 MiB 序列化字节
HTTP maxQueued16–2048,可在支持 slow_client_warning 时使用
warning threshold帧数或字节达到 75%
warning 重新准备两个维度都降到严格低于 37.5%

maxQueuedBytes 是内部 constructor 配置,不提供 HTTP query、SDK 参数或 CLI 开关让远端调用者提高内存预算。

直接交付与缓冲

已有消费者等待 next() 时直接交付,不形成 live backlog。需要入队时检查帧数和字节;空 live queue 允许第一条超大帧原样进入,所以 2 MiB 不是单事件硬上限。

replay 和 synthetic 警告用 forced 标记,不计入 live 队列上限。但 replay 有独立字节预算,不能由“forcePush 绕过 live 限制”推断无限回放内存。

MCP App 的文本回退

非空队列将超过字节限制时,符合条件的 MCP App tool_call/tool_call_update 可把完整 rawOutput.html 清空为字符串,并保留非空 fallbackText。只有缩小后能放入才继续连接;无有效文本回退或仍超限会驱逐 subscriber。

直接交付和 ring 保持原 frame,排队客户端可能收到同 id 的降级 payload。之后从该 id 恢复不会重发它;需要完整文档时应显式查询持久 transcript,并仍遵守分页预算。

Warning 与 eviction

slow_client_warning 是 subscriber 私有、无 id 的提示。live 帧数或字节再溢出时发送 client_evicted,reason 分别为 queue_overflow 或 queue_bytes_overflow,再排空至该终止帧并结束订阅。

响应中 queueSize、maxQueued、queuedBytes、maxQueuedBytes 便于定位哪个维度超限;字节溢出还可带 eventBytes。

client_evicted 不是 session_closed。应用可以重连并按replay 契约恢复,但应该先减少同步渲染、阻塞处理或过重的订阅工作。

订阅与取消

内部 EventBus.subscribe 返回时同步登记 subscriber,避免首次 next() 之前的 publish 丢失。这个保证属于内部 bus,不表示客户端刚取得 AsyncIterable 就已完成远端 HTTP/SSE 握手。

AbortSignal 取消会立即丢弃该订阅的缓冲、移除 listener 和登记;bus close 后 publish 返回 undefined。不要用并发 next() 驱动同一个 queue iterator,应顺序消费。

超过 subscriber 上限时,route 发 stream_error,而不是成功返回永远空的流。客户端应把该错误与会话真正死亡区分。