4.8 KiB
4.8 KiB
系统架构
本文描述直播组件服务的运行边界、数据流和扩展点。实现代码分别位于 apps/server-rust 与
apps/overlay。
核心目标
- 每个账户拥有一个可切换的 Bilibili 直播间、一个 CookieCloud 来源和一条独立监听连接。
- 组件不绑定或选择直播源;账户事件流会提供给该账户所有启用的组件实例。同一 kind 可以拥有多个实例,每个实例独立保存名称、设置、OBS token 和实时通道。
- 平台原始命令先转换成稳定的领域事件,组件不直接依赖 Bilibili
CMD。 - HTTP 会话、直播源、组件、OBS token 和实时通道均以租户为边界。
- 新组件可以增加设置、投影和持久化副作用,而不修改直播连接核心。
运行时数据流
flowchart LR
CC[CookieCloud] --> PF[ProviderFactory]
BL[Bilibili Live] <--> BP[BilibiliProvider]
PF --> BP
BP --> LE[LiveEvent]
LE --> SR[SourceEventRouter]
PG[(PostgreSQL)] --> CR[Component repository/cache]
CR --> SR
SR --> EH[Durable handlers]
SR --> PJ[Passive projection]
PJ --> HUB[Component-scoped EventHub]
HUB --> WS[Authenticated WebSocket]
WS --> OBS[OBS overlay]
SourceSupervisor为每个source_id保持至多一个 provider task。BilibiliProvider使用该用户加密保存的 CookieCloud 凭据构造libilibili客户端;crate 负责 WBI、WebSocket 与压缩包解析,adapter 再把强类型命令转换成LiveEvent。SourceEventRouter按owner_id取得该账户所有启用组件,再由各组件的订阅声明筛选事件类型;source_id只标识账户级监听,不存储在组件行中。- 匹配订阅后,路由器先执行可持久化的
EventHandler,再执行无副作用的EventProjection。 - 投影结果只发布到该
component_id的广播通道。没有全局 WebSocket 事件总线。 - OBS 使用实例级只读 token 订阅一个组件实例,不能读取控制台 API;同类型的其他实例拥有不同
component_id,可在不同 OBS 场景中使用不同样式。
状态所有权
| 状态 | 权威来源 | 内存副本 | 说明 |
|---|---|---|---|
| 用户、TOTP、会话 | PostgreSQL | 无 | Secret 加密,token 只保存摘要 |
| CookieCloud 凭据 | PostgreSQL | provider 构建期间解密 | 每账户一份,不返回浏览器 |
| 直播源和房间 | PostgreSQL | SourceSupervisor |
每账户一个可切换房间和连接 |
| 组件实例与设置 | PostgreSQL | InMemoryComponentStore |
写入成功后刷新热路径缓存 |
| 礼物/表情目录 | Bilibili API | provider catalog | 刷新失败保留最近成功快照 |
| 实时消息 | provider | EventHub 有界广播 |
不作为业务持久化机制 |
| 点歌队列与历史 | PostgreSQL | OBS revision snapshot | handler 事务写入、RLS 隔离 |
| 账户语言偏好 | PostgreSQL | React/OBS runtime | TOML 目录验证、RLS 隔离 |
| PWA 静态壳层 | Docker 镜像 | Cache Storage | 不包含 API 或用户数据 |
启动顺序
AppState::build 按以下顺序启动,避免事件进入未完成的运行时:
- 创建 PostgreSQL 连接池并执行嵌入式迁移。
- 构造加密和 passwordless 鉴权服务。
- 注册内建组件定义。
- 从 PostgreSQL hydrate 组件热路径缓存。
- 创建有界源事件队列、路由器和每组件广播中心。
- 为数据库中所有启用的直播源启动 provider。
- 最后由
main.rs绑定 HTTP 监听端口。
关机时先停止接收 HTTP,再取消所有 provider task,防止容器退出期间继续拉取上游事件。
进程与部署边界
- Node 只存在于 Docker 的前端构建阶段。
- 最终镜像仅运行 Rust 可执行文件,并从
/app/web同域托管静态资源。 - 容器使用 host network,但默认只监听
127.0.0.1:9719。 - Nginx 负责公网 TLS、域名和 WebSocket upgrade。
- CookieCloud 与 PostgreSQL 是外部服务,不由本项目 Compose 创建。
libilibili是源码树中的相邻 crate,由 Compose named build context 注入 Rust 构建阶段。resources/i18n.toml同时输入 Vite 和 Rust 构建;缺少默认语言键的 locale 会使后端测试失败。
代码导航
- 后端模块职责:
apps/server-rust/README.md - 前端路由和状态:
apps/overlay/README.md - 组件扩展指南:
components/README.md - WebSocket 协议:
protocol.md - 安全边界:
security.md