Skip to content

系统架构 ​

YiYi Media 分成两层:控制面负责编排、元数据与账号,节点层负责存储与播放。 两层通过注册中心解耦——节点只需要知道 Config 服务地址,其余服务地址自动发现。

服务模块本身是独立的:Config、User、Media、Gateway、Storage 都作为独立进程运行, 只是可以被聚合到同一个容器里。单机版就是把它们收进一个 yiyi-app 容器, 分布式版则按角色把它们分散到多台机器上。

两种部署形态 ​

接入层 客户端
浏览器
管理后台 / 用户门户
Emby 生态客户端
填地址与账号
Telegram Mini App
Bot 登录
单机版部署(STANDALONE) 1 台服务器 · 3 个容器
yiyi-app
frontend 18080 + gateway 18086 + config 18085 + user 18082 + media 18083 + storage 18084 + play-agent 19090 + license-agent 18088
postgres
四个业务库
redis
缓存

八个服务收进一个容器,Storage 与 Play Agent 为内置节点,随主应用安装、启动、升级;用户只能新增手动反代地址,不能新增外部节点。

分布式部署 · 控制面(DISTRIBUTED) 4 台 · 同一私网
control
config 18085 + postgres + redis + license-agent
user
user 18082
media
media 18083
edge
frontend 18080 + gateway 18086

frontend 内置 nginx 把 /api/* 反代到 127.0.0.1:18086,因此 frontend 与 gateway 必须同机。

分布式部署 · 外部工作节点 N 台 · 任意位置 · 可多实例
storage #1…N
云盘与文件 · 18084
play-agent #1…M
播放代理 · 19090

横向扩容单元:新增外部节点即扩容存储与播放能力,无需改动控制面配置,但受授权配额限制。

存储与依赖 有状态
PostgreSQL
业务库 + yiyi_storage
Redis
media 缓存
云盘 / 本地盘
挂载源

单机版(STANDALONE):

text
┌──────────────── yiyi-app 容器 ────────────────┐
│ nginx/frontend :18080      ← 唯一对外入口     │
│ gateway        :18086      (仅容器内部)     │
│ config         :18085      (仅容器内部)     │
│ user           :18082      (仅容器内部)     │
│ media          :18083      (仅容器内部)     │
│ storage        :18084      (仅容器内部)     │
│ play-agent     :19090      (供本机反代使用)  │
│ license-agent  :18088      (仅容器内部)     │
└───────────────────────────────────────────────┘
           │                         │
      postgres 容器             redis 容器

分布式版(DISTRIBUTED):控制面按 control / user / media / edge 拆到多台机器, Storage 与 Play Agent 作为外部工作节点部署在任意多台服务器上。

两种形态的功能模块完全相同,区别在部署模式、节点模型与许可证 Edition。 完整的模式对比见部署模式与版本选择。

服务职责 ​

控制面 ​

服务默认端口职责
frontend18080Web 界面。唯一的对外 Web 入口,同时把 /api/* 反代到本机 gateway
gateway18086API 统一入口与反向代理,也是授权状态的查询入口
config18085注册中心 + 节点管理。服务发现、节点登记都在这里;一键安装脚本与二进制分发仅分布式版提供
user18082认证、账号、到期与续期、邀请、流量配额、活动日志、播放报表
media18083媒体元数据:媒体库、条目聚合、同步、虚拟库、元数据覆盖、来源访问策略

节点层 ​

节点默认端口职责单机版分布式版
storage18084云盘与文件管理:挂载源、FUSE 挂载、传输任务、刮削、文件缓存、备份、WebDAV 出口内置 1 个(node-local-storage)外部工作节点,可多实例
play-agent19090播放代理:Emby 协议出口、视频流代理、VFS 启播缓存、限速与配额执行、CDN 优选内置 1 个(node-local-play-agent)外部工作节点,可多实例

内置节点由 Config 启动组件幂等创建,随应用容器启动、停止和升级,禁止删除、卸载、独立升级与修改服务类型。 外部节点在「节点管理」里创建后自助部署,按授权配额横向扩容。

存储与依赖 ​

组件默认端口说明
PostgreSQL5432按服务分库:yiyi_config、yiyi_user、yiyi_media、yiyi_storage
Redis6379缓存依赖:媒体元数据缓存、播放入口列表缓存、登录失败计数共享

单机版由同一个 PostgreSQL 实例承载四个数据库,PostgreSQL 与 Redis 走 Compose 私有网络, 应用容器内用 postgres:5432 / redis:6379 访问。分布式版按部署手册配置。

frontend 与 gateway 必须同机

frontend 内置的反代把 /api/* 指向写死的 127.0.0.1:18086。 因此这两个服务不能拆开部署。单机版里它们在同一个容器内; 分布式部署时它们同属 edge 角色,由部署包一起拉起。

服务发现 ​

节点启动时向 Config 服务报到,Config 维护注册表并做心跳与清理:

  • 节点只需要配置注册中心地址 YIYI_CONFIG_HOST 与节点 ID YIYI_NODE_ID。
  • 节点不需要配置 YIYI_SERVER_HOST:启动时凭 YIYI_NODE_ID 向 Config 查询自己的对外地址, 也就是节点管理里登记的 expectedHost。
  • 注册表由两个调度任务维护:registry.cleanup 每 30 秒清理失效注册, infrastructure.heartbeat.check 每 15 秒巡检服务注册、数据库与存储源心跳。

这样做的好处是:换机器、换 IP、加节点,都不用回去改一堆配置文件。

一次播放是怎么走完的 ​

元数据集中在控制面,视频字节由播放节点直连输出,不经过控制面服务器。

01
客户端请求
Emby 生态客户端走的是同一个播放节点入口,客户端只认地址与账号,不需要知道背后是哪台机器。
02
三道准入
依次检查客户端准入(User-Agent 白/黑名单)、该用户是否有权走这个节点与入口、该挂载源对该用户是否可见可播;任一不过直接 403,用户侧只看到「不存在」,不会泄露受限内容。
03
额度前置检查
在输出任何字节之前先查用户级与入口级流量额度,耗尽直接返回 429 并说明是哪一层用完,不会产生一分流量。
04
取网盘直链
直链级适配的网盘(现为 Google Drive 与 115,未来兼容更多)由播放节点直接取签名直链并缓存复用;本地磁盘直读。一次播放有几百个分片请求,逐个换链极易触发风控。
05
按需拉流
按客户端请求的字节范围取数据:本地缓存命中的段直接读盘,缺口向上游按需取,同一个响应里可以混着来,客户端无感,也不要求整片落盘。
06
限速与计量
输出按该用户的带宽限速执行,并按实际写给客户端的字节计入流量额度,本地缓存段与上游段都算,不会因为命中缓存就漏计。
07
播放中复检
播放过程每 30 秒结算一次额度,用完就停发并关闭连接;控制面暂时不可用时给 60 秒宽限,之后一律拒绝。
08
播放上报
客户端按 Emby 协议会话上报开始、进度与结束。这些记录就是播放报表与观影历史的数据来源。

为什么要缓存签名直链

一次播放有几百个分片请求,逐个去网盘换直链极易触发风控,所以播放节点会复用签名直链。 键规则、TTL、负向缓存与并发合并的完整机制见加载与播放速度。

元数据是怎么流动的 ​

刮削与聚合是分开的两件事:

text
网盘文件变更
    │
    ├─ 存储节点:scrape.queue(每 15 秒)执行刮削,产出元数据
    │            file-change-log.scrape(每 15 秒)重放文件变更日志
    │
    ▼
存储节点把变更推给媒体服务
    │
    ▼
媒体服务:sync.queue.process(每 30 秒)消费变更队列
          central-media.sync(每 300 秒)增量同步已启用的媒体库
    │
    ▼
聚合成对外条目(Aggregate Item)
    │
    ▼
播放节点从媒体服务取条目,播放时按挂载源回源到存储节点

这些节奏都可以在调度中心里查看,也可以手动触发。

技术元数据(容器格式、时长、音视频轨道)走另一条链路:播放节点内嵌 ffprobe, 在播放时异步补全,不阻塞播放,也不替代存储侧的刮削。

另外还有一条外部触发链路:入站 Webhook 接收 NAS(如群晖)的文件变更通知, 按 replace_path 剥离挂载前缀后匹配媒体库并分发刮削任务,命中多个来源时全部下发。

客户部署 ​

客户安装走独立部署包 YiYi-Product/YiYi-media-deploy。 两种部署模式用的是同一个仓库、同一个 install.sh。仓库按部署方式分成三个分支, 每个分支根目录都是一套完整部署文件:

部署方式分支拓扑需要的角色变量
单机版(STANDALONE)mainYiYi-media-standalone + -postgres + -redis 三容器无,填服务器地址即可
分布式·控制面同机v2-all-in-one6 个应用服务全在一台机器(数据库/缓存可选外部)无,填服务器地址即可
分布式·按角色多机v3-multi-hostcontrol → user → media → edge 四台每台填自己的角色

两种分布式方式共用同一套控制面与同一份许可证,只是布置不同。

按角色多机时的四个角色:

角色装什么说明
controlpostgres、redis、license-agent、config主服务器,只装一台
userlicense-sync、user用户服务
medialicense-sync、media媒体服务
edgelicense-sync、gateway、frontend网页入口,两者必须同机

跨模式不能靠改角色原地互转

control、user、media、edge 是分布式部署内部的角色,不是独立的部署模式。 单机版与分布式版之间需要授权的专用版本升级操作 + 部署拓扑迁移; 不允许只改 .env 或角色变量切换。详见单机版迁移到分布式版。

节点模型 ​

单机版:两个内置节点 ​

单机版固定内置一个 Storage(node-local-storage)与一个 Play Agent(node-local-play-agent):

  • 由应用容器监管,随主应用启动、停止、升级;
  • 禁止删除、卸载、独立升级与修改服务类型;
  • Storage 自动成为新浏览器会话的默认文件管理节点;
  • 用户只能新增手动反代地址,不能新增外部节点。

分布式版:两条独立扩容轴 ​

分布式版的 Storage 与 Play Agent 是外部工作节点,不由部署包安装—— 登录网页后进「节点管理」创建节点,页面会给出可复制的一键安装命令,复制到目标机执行即可。

它们是一组独立的横向扩展单元:

轴扛什么扩容信号
Storage 节点(18084)网盘配额、刮削算力、文件传输想再接一个盘、刮削排队久、大批新文件入库慢
Play Agent 节点(19090)出口带宽、并发播放晚高峰卡顿、并发上不去、想给不同地区走不同线路

两者都可以多实例、可以部署在任意位置的服务器上,而且加节点不需要改控制面任何配置: 节点凭 YIYI_NODE_ID 向注册中心报到,对外地址由注册中心下发,服务之间自动发现。

完整的扩容决策表见部署模式与版本选择,节点部署步骤见 分布式工作节点部署。

网络与端口 ​

完整端口表与暴露建议见端口与网络。要点:

  • 单机版把前端 18080 与 Play Agent 19090 发布到宿主机;19090 是播放客户端直连端口,可收窄为回环配合反代。
  • 分布式版里 frontend(18080)、storage(18084)、play-agent(19090)需要按需对外可达。
  • config(18085)建议只对内网开放,但节点所在机器必须能访问它。
  • gateway、user、media 不直接对外,都经 nginx 或 gateway 代理。
  • license-agent 默认只绑 127.0.0.1:18088。

生产环境通常在前面再加一层反向代理(Caddy / nginx)做 HTTPS 与域名收敛, 播放端点会走独立域名。详见反向代理与域名。

授权在架构里的位置 ​

授权状态由各服务在本地校验:每个服务读自己那份租约文件判断能否放行, 不需要每次请求都去问授权中心,所以授权中心断连不会立刻影响业务。

签名租约里的 Edition(STANDALONE / DISTRIBUTED)是最终授权依据, 由服务端强制执行能力边界。前端只消费后端返回的派生能力,不直接决定是否允许节点操作。

只有「已激活」与「宽限期」两种状态允许业务操作。越过宽限截止进入受限模式: 不删数据、不卸卷,保留管理员登录、激活、状态查询、日志导出与备份, 拒绝新播放会话、文件写入、调度任务与新节点注册。 授权不限制用户数,也不绑硬件。

完整规则、Edition 匹配与受限模式行为见授权与版本。

相关阅读 ​

自托管媒体管理系统(单机版 / 分布式版) · 想先体验或有问题,加 Telegram 群:t.me/yiyi_media_group