Files
lxc-streamutils/docs/architecture.md
T
2026-07-16 00:12:26 -07:00

3.9 KiB

系统架构

本文描述直播组件服务的运行边界、数据流和扩展点。实现代码分别位于 apps/server-rust 与 apps/overlay。

核心目标

  • 每个账户固定绑定一个 Bilibili 直播间和一个独立直播源。
  • 一个直播源只建立一条上游连接,但可以把事件投递给多个组件实例。
  • 平台原始命令先转换成稳定的领域事件,组件不直接依赖 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]
  1. SourceSupervisor 为每个 source_id 保持至多一个 provider task。
  2. BilibiliProvider 使用该用户加密保存的 CookieCloud 凭据获取 Cookie,并把原始消息转换成 LiveEvent。
  3. SourceEventRouter 同时使用 owner_id 与 source_id 查找启用的组件,并再次检查组件归属。
  4. 匹配订阅后,路由器先执行可持久化的 EventHandler,再执行无副作用的 EventProjection。
  5. 投影结果只发布到该 component_id 的广播通道。没有全局 WebSocket 事件总线。
  6. OBS 使用组件级只读 token 订阅一个组件,不能读取控制台 API。

状态所有权

状态 权威来源 内存副本 说明
用户、TOTP、会话 PostgreSQL 无 Secret 加密,token 只保存摘要
CookieCloud 凭据 PostgreSQL provider 构建期间解密 不返回浏览器
直播源和房间 PostgreSQL SourceSupervisor 每用户固定一个房间
组件实例与设置 PostgreSQL InMemoryComponentStore 写入成功后刷新热路径缓存
礼物/表情目录 Bilibili API provider catalog 刷新失败保留最近成功快照
实时消息 provider EventHub 有界广播 不作为业务持久化机制
PWA 静态壳层 Docker 镜像 Cache Storage 不包含 API 或用户数据

启动顺序

AppState::build 按以下顺序启动,避免事件进入未完成的运行时:

  1. 创建 PostgreSQL 连接池并执行嵌入式迁移。
  2. 构造加密和 passwordless 鉴权服务。
  3. 注册内建组件定义。
  4. 从 PostgreSQL hydrate 组件热路径缓存。
  5. 创建有界源事件队列、路由器和每组件广播中心。
  6. 为数据库中所有启用的直播源启动 provider。
  7. 最后由 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 创建。

代码导航