加载与播放速度
这一页讲为什么快,以及单机版的资源上限在哪里。封面、媒体列表、起播这三件事 各自走不同的加速链路,配置入口都在播放设置与系统配置里。
| 你要等的 | 快在哪 | 默认状态 |
|---|---|---|
| 封面与缩略图 | 海报直连 TMDB 的 CDN,不占你的带宽;经过服务器的图片则落本地磁盘缓存 | 已生效 |
| 媒体列表与详情 | 元数据缓存在 Redis 里,列表与详情是内存级响应 | 默认开启 |
| 起播与拖动 | 智能启播只缓存开场所需字节;签名直链复用避免反复换链触发风控 | 已生效 |
| 传输稳定与速度 | 缓存盘按 Range 落盘、上游直连、CDN 候选 IP 优选 | 已生效 |
一、封面与图片
大部分海报根本不经过你的服务器
客户端拿到的海报地址会被直接改写成 TMDB 的 CDN 直链,并且按客户端请求的宽度选最小够用的档位:
| 客户端要的宽度 | 实际取哪一档 |
|---|---|
| ≥ 780 或不指定 | original |
| ≥ 500 | w780 |
| ≥ 342 | w500 |
| ≥ 185 | w342 |
| ≥ 154 | w185 |
| 更小 | w154 |
所以海报流量走 TMDB 的 CDN,不占你的出口带宽,也不会因为你的服务器慢而卡图。 列表页只要小图、详情页要原图,这个档位选择是自动的。
你上传的封面(全局 Logo、媒体库封面、元数据覆盖里换的封面)走的是另一条: 地址被改写成 config 服务直连,绕过媒体服务与公网网关,所以不受后台接口负载影响。
经过服务器的图片有一层磁盘缓存
有些客户端会自行构造图片地址去请求播放节点。这类请求会进播放节点的图片缓存:
- 用户头像转发给 user 服务,海报与缩略图转发给 media 服务,两者都缓存整张图
- 缓存位置、容量、保留时间的默认值:目录
./image_cache、容量 500 MB、保留 7 天、清理轮询 10 分钟 - 淘汰是双阈值:先按最近最少使用淘汰,再按「最后一次访问」超期淘汰
- 每张图旁存一个边车文件记录内容类型、ETag、最后访问与过期时间
- 命中时响应头会带
X-Image-Cache: HIT——想确认某张图有没有走缓存,看这个头就行 - 未命中时用后台 30 秒超时拉取:即使客户端中途断开,图片也会完成拉取并缓存下来, 下一个用户直接命中。这是「第一个人慢、后面都快」的原因
换了海报但页面还是旧图
图片缓存没有按条目失效的能力,改完封面后旧图会继续命中到 7 天保留期到期。 想立刻生效,到播放设置对该节点点「清空全部缓存」再让用户刷新。
前端侧的配合
媒体列表与播放器里的图片用了懒加载,超过屏幕的图不会立刻请求; 加载失败有兜底占位,不会出现破图。
二、视频信息(列表与详情)
元数据缓存在 Redis 里
媒体服务的查询结果默认缓存在 Redis 中,默认开启。
这份缓存是「永不过期」的
它没有设置过期时间,完全靠主动失效:媒体同步完成后、媒体库被修改或删除后, 系统会去清掉受影响的缓存。
这个设计的好处是列表与详情永远是内存级响应,不会出现「缓存过期后第一次访问特别慢」。 代价是:如果你绕过系统直接改了数据库,页面不会自己更新—— 要走一次同步,或者改动一下媒体库来触发失效。
Redis 不可用时会退化为不缓存,功能不受影响,只是变慢。
已校验的会话在节点本地留 5 分钟
用户登录态校验通过后,播放节点会在本地记住这个会话 5 分钟。 这 5 分钟内的请求不再回问用户服务,所以连续播放、拖动、切集都不会每次都付一次鉴权开销。
存储侧的目录缓存
「目录缓存过期时间」控制云端目录列表在存储节点上缓存多久:
| 档位 | 效果 |
|---|---|
| 永久(仅手动刷新)(默认) | 浏览与刮削扫描最快,但云端新增的文件要手动刷新才看得到 |
| 5 分钟 / 30 分钟 / 1 小时 / 6 小时 / 1 天 | 到期自动重拉目录,时效性与速度的折中 |
目录缓存越久,大目录的浏览与刮削扫描越快。如果你刚在网盘里加了文件却看不到, 先到文件管理点一次刷新,或把这个值调短。
目前只有全局值生效
界面上这一项属于挂载源配置,但挂载源级覆盖当前不生效,实际用的是全局值。
三、播放起播与传输
智能启播缓存:不缓存整片,只保证开场够用
传统做法是把整个文件缓存到本地才能加速,代价是几 TB 的硬盘也存不下几部片。 智能启播反过来:只保证开场所需的字节在本地。
它先用 ffprobe 探测容器元数据的真实位置,只持久化「基础头部 + 必要索引 + 少量开场字节」, 探测成功即停,不会为了缓存而把文件读完(为什么不能只缓存头尾,见核心概念)。
三档空间预设(数值是单文件口径):
| 档位 | 基础头部 | 降级尾部 | 单文件硬上限 | 探测流量预算 |
|---|---|---|---|---|
| 节省空间 | 8 MB | 1 MB | 16 MB | 8 MB |
| 智能平衡(默认) | 8 MB | 1 MB | 32 MB | 16 MB |
| 更稳启播 | 16 MB | 1 MB | 64 MB | 16 MB |
推荐的「智能平衡」下,一部片最多只占 32 MB 缓存,却能让重复播放直接起播。
混合读取是另一处关键设计:一个 HTTP 响应里可以同时包含「本地缓存段」与「上游直传段」, 并保持原文件偏移。所以缓存不全也不影响播放,拖动到没缓存的区间会直接从网盘拉。
首次播放仍然要回源
智能启播优化的是重复播放与多人同时看,不是第一次。 第一次播放某个文件时这些数据还不存在,必须从网盘读——这是设计前提,不是缺陷。
起播字节还会在内存里保留 1 分钟:同一部片短时间内重开、或第二个人紧接着看, 起播比第一次快得多。
签名直链复用:防的是云盘风控
一次 4 GB 文件的播放大约产生 500 次分片请求。如果每个分片都去网盘换一次直链, 极易触发云盘风控。播放节点会缓存签名直链:
- 键是「挂载源 + 条目」(多账号网盘再加上账号)
- 有效期从直链自带的过期参数推算;本地拼装的直链(Google Drive 属于这类)没有过期参数, 不设有效期,只在云盘返回 401/403 时重新获取一次
- 令牌失效这类错误会做 5 分钟负向缓存,避免反复打云盘接口把额度耗光
- 同一时刻的并发请求会合并成一次远端调用,不会几个人同时看就发几次请求
直链级适配目前覆盖 Google Drive 与 115 两类网盘,未来会兼容更多; 本地磁盘直读,其余来源的播放字节流由存储节点代理,不走这套换链逻辑。
CDN 候选 IP 优选
对 Google Drive,播放节点会解析候选 CDN 地址、实测延迟与吞吐, 在优选池里轮询使用并保留表现最好的若干个(池上限 5 个)。 切换对播放无感——已经在传的连接不会被打断,新连接走更快的地址。
多账号共享池
Google Drive 支持配置多个账号:请求会在账号间分流, 某个账号配额受限或认证失效时会切到其它可用账号,而不是让播放直接失败。
反向代理这一层也要配对
播放是 Range 分段流,代理层的响应缓冲、超时、压缩设置会直接影响速度与稳定性。 这几个参数必须按反向代理与域名里的说明配置: 关掉响应缓冲、拉长读写超时、别开压缩、透传 Range。
四、哪些没有缓存
写清楚边界,免得你按错误的预期去查问题:
- 图片缓存没有按条目失效,只有清空全部
- 元数据缓存永不过期,靠主动失效;绕过系统改库不会自动反映
- 首次播放必须回源,智能启播不改变这一点
- 没有下一集预取、没有海报预加载这类预加载能力
系统配置里的「响应缓存」开关目前不生效
JSON 层面的缓存加速由上方的 Redis 元数据缓存提供,无需额外操作。详见系统配置。
五、怎么调
| 想改善 | 去哪里调 |
|---|---|
| 图片占磁盘太多,或想立刻换掉旧海报 | 播放设置 → 图片缓存(容量 / 保留时间 / 清空) |
| 起播更稳,或想少占缓存盘 | 播放设置 → VFS 文件缓存(缓存用途选启播加速,再选空间档位) |
| 网盘风控严、频繁 403 | 播放设置 → CDN 优选;文件运维 → 传输设置里的 API 调用间隔 |
| 云端新文件久久不出现 | 把「目录缓存过期时间」调短,或手动刷新目录 |
| 列表与详情偏慢 | 检查 Redis 是否可用;确认元数据缓存没被关掉 |
| 机械盘上多路并发卡顿 | 播放设置里会识别缓存盘是机械盘还是固态盘并给出告警,按提示收紧预读窗口 |
六、单机版的资源上限与分布式版的横向扩容
这是两种部署模式在性能规划上最关键的差别。
单机版:三个容器,一份资源
单机版把八个服务收进一个 yiyi-app 容器,跑在同一台服务器上。所以:
- CPU 与内存是共享的。聚合容器内多个 JVM 各自有堆上限,媒体处理并发、调度线程、 Storage 传输并发都按单机默认值收敛。后台操作与播放会竞争同一份资源。
- 出口带宽是共享的。播放字节从同一台机器出去,晚高峰并发受这台机器的带宽上限制约。
- 磁盘是共享的。数据库、上传文件、Storage 的
spool与读缓存、Play Agent 的vfs-cache与image-cache都落在同一块盘上,需要预留足够空间与 IOPS。 - 不能加节点扩容。单机版固定内置一个 Storage 与一个 Play Agent,
maxStorageNodes=1/maxPlayAgentNodes=1只代表这两个内置节点, 不代表可以新增节点。纵向提升服务器配置是单机版唯一的扩容方式。
不要按「加节点」去规划单机版容量
看到容量或并发不够时,单机版能做的只有升级硬件、调低缓存档位、或把播放线路收到本机反代之后。 真正的横向扩容需要先升级为分布式版。
分布式版:三条独立的扩容轴
分布式版把控制面拆到多台机器,并把存储与播放变成两条独立的外部工作节点扩容轴:
| 轴 | 扛什么 | 扩容信号 |
|---|---|---|
Storage 节点(18084) | 网盘配额、刮削算力、文件传输 | 想再接一个盘、刮削排队久、大批新文件入库慢 |
Play Agent 节点(19090) | 出口带宽、并发播放 | 晚高峰卡顿、并发上不去、想给不同地区走不同线路 |
| 控制面角色拆分 | 元数据、账号、网关的负载隔离 | 控制面 API 变慢,或想让播放流量与控制面互不影响 |
- 播放字节走「网盘 → 播放节点 → 客户端」,不经过控制面服务器。把 Play Agent 部署到另一台机器后,控制面带宽就完全不被播放占用。
- 节点可以部署在任意数量、任意位置的服务器上,加节点不需要改控制面任何配置。
- 节点数量受授权配额限制(
maxStorageNodes与maxPlayAgentNodes), 扩容前先确认配额,见授权与版本。
跨节点并行来自哪里
跨节点并行来自「谁收到刮削请求,谁在自己进程里立刻开工」,而定时兜底任务每次只派给一个节点。 所以加 Storage 节点提升的是手动发起与自动增量的吞吐,不是定时任务的并行度。