docs(route): define deployment-wide SFU admission

This commit is contained in:
AAA committed 2026-08-23 00:48:58 +08:00
1 parent 6b0b1a37e3
commit 56ae363838
5 files changed
+66 -10

No files matched your search

@@ -184,6 +184,20 @@ SFU and TURN remain bounded fallback resources with independent deployment-wide
admission. Resource exhaustion produces the next bounded candidate, an explicit
wait, or failure; it never creates unbounded central fanout.
For the single-process deployment, SFU admission is one injected in-memory
authority with deployment-wide ingress and egress counters. Enabling LiveKit
requires explicit positive safe-integer `SFU_INGRESS_CAPACITY` and
`SFU_EGRESS_CAPACITY` values; neither has a product default and neither is
derived from endpoint capacity, Viewer admission, or a fixed root count. One
Host publication consumes one ingress unit and every SFU subscription consumes
one egress unit. A concurrently media-producing candidate consumes its actual
units in addition to the committed generation. The controller reserves against
the exact room, share, and publication generation before token issuance,
promotes that reservation at route commit, and idempotently releases it on
abort, timeout, participant loss, share rollover, room stop, or room deletion.
A multi-process application deployment requires a shared atomic admission
authority before it may claim these values are deployment-wide.
## Current Production Divergence
Production release `9461e20` predates this revision. Its exact behavior is owned
+15 -9
View File
@@ -219,7 +219,8 @@ PEER_ASSISTED_MEDIA=true
LIVEKIT_URL=wss://share.example.com
LIVEKIT_API_KEY=<GENERATED_LIVEKIT_API_KEY>
LIVEKIT_API_SECRET=<INDEPENDENT_SECRET_OF_AT_LEAST_32_BYTES>
MAX_SFU_ROOTS_PER_ROOM=2
SFU_INGRESS_CAPACITY=<MEASURED_DEPLOYMENT_INGRESS_COPIES>
SFU_EGRESS_CAPACITY=<MEASURED_DEPLOYMENT_EGRESS_COPIES>
```
The rejected `PEER_ICE_TURN_*` participant-wide tuple is removed; supplying any
@@ -247,7 +248,7 @@ errors to the result.
`PEER_ASSISTED_ROOM_IDS` is retired. Supplying it, even blank, fails startup so
that a stale room-1 deployment cannot silently retain the old scope. With
`PEER_ASSISTED_MEDIA=true`, every normal room receives peer-assisted routing,
optional LiveKit fallback, and the same per-room root/fanout/failure guards.
optional LiveKit fallback, and the same deployment resource/fanout/failure guards.
Every ordinary peer connection remains STUN-only; selected-edge TURN is still
issued only to a current controller-selected edge. There is no browser control,
percentage rollout, or second router.
@@ -282,14 +283,19 @@ sender atomically on `screener-v6`; restore the exact prior environment and
release together when rolling back.
The three `LIVEKIT_*` values must either all be absent or all be present, and a
complete tuple requires `PEER_ASSISTED_MEDIA=true`. An empty tuple keeps the
optional SDK and server path dormant. `LIVEKIT_URL` must be a plain `ws:` or
`wss:` origin with no `/rtc` suffix; production requires `wss:`.
complete tuple requires `PEER_ASSISTED_MEDIA=true` plus explicit positive
safe-integer `SFU_INGRESS_CAPACITY` and `SFU_EGRESS_CAPACITY` values. The two
capacities have no defaults and must be selected from the instance's measured
publisher/subscriber/bitrate and accepted concurrency matrix. Supplying either
capacity without the complete fallback configuration fails startup rather than
silently enabling or ignoring a partial policy. An empty tuple with neither
capacity keeps the optional SDK and server path dormant. `LIVEKIT_URL` must be a
plain `ws:` or `wss:` origin with no `/rtc` suffix; production requires `wss:`.
`LIVEKIT_API_SECRET` must contain at least 32 bytes and must not reuse
`SITE_ACCESS_PASSWORD`. In that same held release, `MAX_SFU_ROOTS_PER_ROOM` defaults to
2 and accepts only 1 or 2; it is ignored when LiveKit is not configured. These
credentials authorize short-lived LiveKit room tokens and do not provide E2EE:
the LiveKit operator can access ordinary SFU media.
`SITE_ACCESS_PASSWORD`. These credentials authorize short-lived LiveKit room
tokens and do not provide E2EE: the LiveKit operator can access ordinary SFU
media. The current admission owner is one Screener process; run only one
application process until a shared atomic ledger is implemented.
For the first candidate canary, use an isolated instance and a protected
persistent room whose ID is stable across restarts. Restart the application and
+33
View File
@@ -533,6 +533,39 @@ the server must. Redundancy can improve recovery but costs traffic and
coordination; removing redundancy leaves a recovery interval after a relay is
lost.
## Deployment-Wide SFU Admission
LiveKit's official benchmark guidance says each room must fit on one SFU node
and identifies published tracks, subscribers, and bytes forwarded per subscriber
as separate capacity drivers. Its room `maxParticipants` setting is a participant
count guard; it does not express Screener's Host-publication ingress or
per-subscription egress budget. The application therefore needs its own typed
admission boundary instead of treating a root count or the SDK room setting as
resource evidence.
For the current single application process, one O(1) ledger owns two explicitly
configured positive safe-integer capacities: each Host publication uses one
ingress unit and each authorized SFU subscription uses one egress unit. There is
no built-in default or fixed root count. A candidate reserves its full actual
ingress/egress demand under exact room/share/publication identity before any
token is issued; concurrent old and candidate generations are both charged.
Commit promotes the candidate and releases the superseded generation. Abort,
timeout, disconnect, share rollover, room stop, and room deletion use the same
idempotent release. Capacity exhaustion leaves the current route unchanged and
returns control to the bounded fallback sequence.
These capacities are operator inputs derived from the actual instance, codec,
representation, bitrate, and accepted concurrency matrix. LiveKit's published
example benchmark cannot supply Screener defaults. A later multi-process
Screener deployment needs a shared atomic ledger; independent process-local
counters would not be deployment-wide admission.
Primary sources accessed 2026-08-22:
- [LiveKit benchmarking](https://docs.livekit.io/transport/self-hosting/benchmark/)
- [LiveKit server configuration sample](https://github.com/livekit/livekit/blob/master/config-sample.yaml)
- [LiveKit access tokens and room configuration](https://docs.livekit.io/frontends/reference/tokens-grants/)
## Route Screening
| Route | Where copies are emitted | Endpoint cost | Evidence status |
+2
View File
@@ -376,6 +376,8 @@ Parent selection 使用硬过滤加字典序,不建立综合质量评分器。
所有非服务器端点共享一个 server-authoritative steady outbound media-copy capacity:唯一配置 `ENDPOINT_MEDIA_COPY_CAPACITY` 默认 `2`,只接受 `1`、`2` 或 `3`,不兼容旧键。peer child 或 Host publication 各占一份,upstream receive 免费,committed selected TURN 只替换同一份 edge transport;SFU subscriber egress 与 TURN allocation 使用独立 server admission。客户端 capability 只能收紧该值,不能按角色、浏览器、UA、设备或页面可见性建立另一套 policy。服务端通过 v6 `authenticated.endpointMediaCopyCapacity` 把最终值交给 Web 与 Native;Native 不从 `maxViewers` 推导发送预算,普通 admission、peer-assisted child assignment 和槽位分配共用该值。代码通过一个 shared accounting guard 执行,不在 Host、Viewer、active、recovery 或 migration 分支重复 magic number;client/server/native wire 随该能力原子升级。首个迁移波次在独立 server admission 就绪前保留现有 SFU subscriber 与 room-wide selected-lease 安全护栏,但不把其固定值当作产品 policy;`C=3` 满载时必须在发出会产生第四份 Host media copy 的 token/grant 前明确等待或失败。
SFU admission 在应用单进程中只有一个注入实例。LiveKit credential tuple 完整时,`SFU_INGRESS_CAPACITY` 与 `SFU_EGRESS_CAPACITY` 都必须显式配置为正 safe integer;它们没有产品默认值,也不从 Viewer 数、endpoint cap 或历史 root 数推导。账本只保存全局已用计数和按 exact room/share/publication generation 索引的 `reserved | committed` 条目:Host publication 计 ingress `1`,每个订阅计 egress `1`,候选与旧 generation 并存时按实际副本同时计数。route controller 先 reserve,再 prepare 和签发 token;media proof 后 commit candidate 并释放同房旧 generation,任何失败、超时、失联、分享换代、停止或删房都调用同一幂等 release。所有操作是 Map lookup 与整数加减,不扫描房间或参与者。当前切片不实现 TURN allocation admission,不改 parent selection,也不预建多进程协调;多应用进程部署必须先增加共享原子 owner。
普通 Web relay 把收到的 remote track 加入独立 downstream `RTCPeerConnection`,因此可能逐跳解码和重编码;浏览器不保证跨连接 shared encode。每条 ordinary child 是独立网络副本,实际 encode time、CPU/GPU、bitrate、loss、frame rate、depth 和 recovery 必须测量。
迁移使用 exact room/share/session/revision/assignment/connection/media-binding identity。旧 route 保持 active,candidate 在 active map 外准备;只有当前代 live track、正 RTP 与 decoded-frame progress 同时成立时才原子 promotion。失败、超时、代次变化或授权撤销销毁 candidate 并保留或恢复旧 route。Make-before-break 的 overlap 由统一端点容量、单个有界 `TransitionOverlapSlot` 和 typed server-resource admission 同时决定。
+2 -1
View File
@@ -52,7 +52,7 @@ SFU/TURN 的 publication、subscription、transport、server-resource accounting
- 原生 shared encode relay:具备原生 relay 能力的非服务器端点同样受统一服务端权威下游容量约束,并应复用兼容编码输出而不再次编码。当前普通浏览器 relay 使用逐边重编码的标准 WebRTC 路径,不伪称 shared encode。
- SVC 重开条件:当前标准 Web/LiveKit SVC 已静态拒绝为 `no-go-web-svc-cross-path-hardware-contract`。sender `scalabilityMode` 没有 direct/peer receiver 对应的按层选择或跨 PeerConnection shared-encode 契约;requested/applied mode、Media Capabilities `powerEfficient` 和 RTCStats encoder 字段也不能证明没有静默软件 fallback。Pinned client 2.22.0 还会把 screen-share SVC 覆盖为三层 temporal-only `L1T3`,不满足低分辨率 base 与最多两层。只有未来 native sender 能明确选择硬件编码器、最多发布两层、将同一编码输出复用于 direct/peer/SFU、保持每条路径独立选择并通过真实游戏和亚秒延迟门槛时,才可用新的 capability decision 重开 SVC;不能把浏览器 API 支持或 UA 推断当成采用理由。
- 分包/分层多树实验:把编码包、对象或可独立解码层拆到多个 peer 路径以分散上传,只能在独立 spike 中验证。必须保持亚秒级,处理多父重组、排序、丢包恢复、关键帧、同步和节点退出;未通过门槛前不进入产品路由控制器。
- SFU/TURN 中央兜底:产品部署可以提供有界 SFU 与可选 TURN 资源,但不要求用户选模式,也不得默认变成整房 always-SFU。只有 Host 拥有一个 authoritative publication;SFU-fed Viewer 具备独立出站证明时才可继续 relay,严格受限 Viewer 保持 leaf。TURN 是某条授权 logical edge 或 Host-SFU ingress 的 selected transport,不是拓扑节点。central egress/admission、temporary overlap 和 exact fallback 由同一个 route controller 与资源账本约束,不能由固定 root 数或普通端点 child 数代替。
- SFU/TURN 中央兜底:产品部署可以提供有界 SFU 与可选 TURN 资源,但不要求用户选模式,也不得默认变成整房 always-SFU。只有 Host 拥有一个 authoritative publication;SFU-fed Viewer 具备独立出站证明时才可继续 relay,严格受限 Viewer 保持 leaf。TURN 是某条授权 logical edge 或 Host-SFU ingress 的 selected transport,不是拓扑节点。启用 LiveKit fallback 时必须显式提供无默认值的正整数 `SFU_INGRESS_CAPACITY` 与 `SFU_EGRESS_CAPACITY`;一份 Host publication 占一个 ingress,每份 SFU subscription 占一个 egress,实际并行 candidate 另占资源。单进程部署由一个 O(1) 全局账本在发 token 前按 exact room/share/publication fence reserve,commit 后替换旧 generation,abort、timeout、disconnect、share rollover、room stop/delete 都幂等释放。固定 root 数和普通端点 child 数都不能代替该准入;资源耗尽进入下一条有界候选、明确等待或失败。多应用进程部署必须先引入共享原子账本,不能把各进程本地计数相加冒充全局准入。
- 分享端桌面封装:用 Electron 固定 Chromium 版本、改善选源/热键/系统音频体验,同时保留 Web 观看端。
- Windows 应用音频:Windows 11 Native sender 使用本地 opaque window target 绑定 HWND、PID 与进程创建时间,只捕获所选游戏及其子进程的音频,避免把语音聊天或通知声一并分享;“全部系统声音”只能由分享者显式选择。普通 Windows 10 不具备当前 process-loopback API 门槛,必须明确标为未解决/不支持而不是伪兼容。浏览器无法证明或隔离任意进程音频时必须如实提示,原生捕获失败、无声或进程退出不得静默扩大为整机捕获。
- 受限网络增强:短期鉴权 TURN 只有在完整、默认关闭的部署配置和当前 route controller 明确授权时可用;普通 peer PC 从创建起保持 STUN-only,不得向整个 participant、房间或所有 peer connections 预发 TURN candidates。凭据必须绑定 exact room/share/session/route/connection generation,短期有效、内存态、受配额约束且不进入 URL、日志、浏览器持久化或 SQLite。TURN 只替换授权 edge 的 transport;Host 无 direct first-level path 时可作为单条 Host-SFU ingress 的 transport。TURN 不得被描述为更高清的传输方式。
@@ -139,6 +139,7 @@ SFU/TURN 的 publication、subscription、transport、server-resource accounting
- Given ADR-0004 的任一硬门槛只有在引入 Encoded Transform/DataChannel/WebCodecs 媒体、自定义拥塞控制、FEC/RTX、多树、综合评分、转码、codec ladder、浏览器 RTP 注入 hack 或放宽 endpoint capacity 后才能满足,When 结束 bounded spike,Then 放弃并删除该浏览器 relay 实验路径,保留标准 P2P 与整体路由模型已接受的 fallback;后续 native shared encode sender 仍按独立 ADR 推进,但不能据此把失败的 relay 拓扑判为通过。
- Given 新观看者会使预计总上行超过安全预算,When 其请求加入,Then 系统只选择整体路由模型已授权且满足配置容量与资源准入的路径;没有合格路线时明确等待或拒绝,而不是创建超过配置容量的 ordinary edge 或持续堆积发送队列。各 transport 的拥塞控制适应该路径,应用证据只改变拓扑资格,不能合成全房降档。
- Given SFU 或 TURN 参与路线,When 计算准入、迁移 overlap 或失败恢复,Then 同时检查统一端点容量和独立的 server ingress/egress、SFU、TURN 资源预算;不得把普通端点 child 数当作 server cap,也不得借兜底形成无界整房 fanout。
- Given 配置完整 LiveKit credential tuple,When `SFU_INGRESS_CAPACITY` 或 `SFU_EGRESS_CAPACITY` 缺失、非正整数或超出 JavaScript safe-integer 范围,Then 服务必须在启动时 fail closed。Given 两项均有效,When 当前 committed 与 reserved 的 ingress 或 egress 会越过任一部署容量,Then controller 必须在签发任何新 SFU token 前拒绝该 candidate,并保持旧 route 和计数不变。
- Given Host、relay parent 或 leaf 处于受限网络,When direct/peer 路径不足,Then 只执行 ADR-0005 授权的 publisher、subscriber、selected transport 和 fallback sequence;不得靠未授权的固定数量或静态 lease 假设猜测实现。
### 质量和恢复