昨晚想用 emby看个电影,一直卡加载,于是再弄一下反代。让我疑惑的是,搞好反代之后依然是卡加载。即使我特地挑了一台带宽比较大的 vps 当反代。
于是我觉得可能是软件的问题,看了下 emby 有没有更新,发现没有更新。于是重装了下恢复默认设置,看不了。又看了下是不是 emby 设置有问题,搞了下视频渲染、图形接口、还有硬件加速。结果还是卡加载。
让我很疑惑,如果直接在 vps 上面用 wegt 下载 emby 的视频速度还挺快,用 idm 在本机上下载也是挺快的,但为什么就是一直加载呢?
今天早上起来又研究了下,换了台 ping emby 源站延迟比较低的美西 vps 反代
就能正常观看了。
影响 emby 反代的因素
Emby 一直转圈加载的问题不在于网络带宽,而在于网络延迟(Latency)以及Emby播放器在这种高延迟网络下所采用的流媒体协议(HLS)。
和 sfpt 传输文件夹龟速一样,emby 加载半天的原因也是单次传输的固定开销过大。
sfpt 每次传输文件需要在应用层重复“打开-操作-关闭”交互过程,所以文件夹的 n 个小文件就要重复 n 次。
如果是 cubic
的话。
- 把一整个视频文件,在服务器端“虚拟地”切成无数个几秒钟长短的小文件(视频切片),然后播放器一个一个地去请求、下载、播放。
- 连接刚建立时,它并不知道链路有多宽,所以它会从一个非常小的“拥塞窗口”(可以理解为初始速度)开始发送数据。
- 为了确认网络能够承受,它必须等待接收方(播放器)发回一个“确认收到了”的回执(ACK 包),然后才能把“窗口”加倍,提高速度。
- 因为整个代理链条(从播放器到VPS,再到源站)的端到端总延迟非常高,这个“确认回执”就需要很长时间才能返回给源站服务器。这就导致了TCP的“提速过程”极其缓慢。
- 那个几秒钟的小切片文件本身非常小。往往在 TCP 的拥塞窗口还没来得及扩大到能利用 10 MB/s 带宽的程度时,这个小切片就已经传输完毕了。
- 紧接着,播放器又去请求下一个小切片,于是 TCP 又开始了一轮全新的、从零开始的“慢启动”和“漫长等待”。
因为我是 bbr+fq
。每一次独立的HTTP请求(比如请求一个HLS切片),都需要经过一次TCP的“三次握手”。这个过程至少需要消耗一个RTT的时间,而在此期间,没有任何应用数据被传输。对于HLS这种需要成百上千次请求的协议,这部分固定的时间开销会迅速累积。简单来说就是 延迟*n
。
像 idm 和 wget 这种。wget 是单分片,在下载一个文件时,默认只会建立一个TCP连接,发起一次HTTP请求,然后就专心致志地、连续不断地接收数据流,直到整个文件下载结束。Idm 则是并行分片,但也就 8 片分片。而hls 这种是成百上千片,串行分片,效率就低了很多。
综上所述,emby 反代选择和源站延迟更低的 vps 更加重要。
BBR
Bbr 能主动探测网络链路的最大容量和网络的最低延迟。瓶颈带宽 (Bottleneck Bandwidth),往返时间 (Round-trip Time)。
FQ
FQ 的全称是 FairQueuing(公平队列)。它会把不同的网络连接(视频流、网页、游戏数据等)放进各自的队列里,然后像发牌一样,公平地、轮流地从每个队列里取出数据包发送出去。这样就确保了下载大文件的请求不会完全阻塞需要快速响应的游戏或 SSH 请求。
反向代理的作用
大家可能看了上面会疑惑,本机到 emby 服务器普通线路本来就要挤国际出口,中间加一层反代服务器有什么用?如果不是优化线路还不是挤国际出口?
其实反代服务器充当了一个缓冲的作用。
- 如果没有反代服务器,emby 客户端是向 emby 服务器即用即取。网络波动会对播放有巨大的影响。这也是为什么早上观看好好的,晚高峰观看却卡的不得了的原因。
- 如果有反向代理服务器,相当于中间加了一层缓冲。核心是对抗和吸收不稳定的网络波动,让从源站获取数据变得平滑可靠。由于和源站之间的网络较好,能快速将源站数据下载接收下来,然后将收到的数据相对稳定地持续,稳定发向播放器。
可以将反代服务器想象成一个蓄水池,没有蓄水池河流时而汹涌时而干涸,但是有了蓄水池就能让河流平稳。
- 反向代理将数据的“获取”和“交付”两个环节解耦了。
如果反向代理服务器和 emby 源站之间的延迟过大,受网络影响就会过大。
如果播放器到 emby 源站是一次劣化的话,中间再套一次延迟大的反代相当于二次劣化
。
反代设置
# /etc/caddy/Caddyfile
your.domain.com { # <-- 修改为你的域名
reverse_proxy http://direct.zox.show { # <-- 修改为你的Emby服务器域名
transport http {
# 读取超时:等待后端发送数据的最长时间,设为10分钟以防流媒体中断
read_timeout 600s
# 连接超时:尝试与后端建立连接的最长时间
dial_timeout 10s
}
# 禁用响应缓冲
flush_interval -1
header_up Host {upstream_host}
}
}
# /etc/nginx/sites-available/emby-proxy.conf
# HTTP to HTTPS Redirect
server {
listen 80;
listen [::]:80;
server_name your.domain.com; # <-- 修改为你的域名
location / {
return 301 https://$server_name$request_uri;
}
}
# HTTPS Reverse Proxy
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your.domain.com; # <-- 修改为你的域名
# --- SSL/TLS Configuration ---
ssl_certificate /path/to/your/ssl/fullchain.pem; # <-- 修改为你的证书路径
ssl_certificate_key /path/to/your/ssl/privkey.pem; # <-- 修改为你的私钥路径
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# --- Reverse Proxy Core ---
location / {
proxy_pass http://backend_emby_server_ip:8096; # <-- 修改为你的Emby服务器内网IP和端口
# --- Forward Headers to Backend ---
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# --- WebSocket Support (Essential for Emby) ---
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# --- Streaming Optimizations (Essential for Emby) ---
proxy_buffering off; # 关闭响应缓冲,收到后端数据后立刻转发给客户端,防止视频卡顿
proxy_request_buffering off; # 关闭请求缓冲,对于大文件上传等有益
# 延长各种超时时间至一小时,防止因后端处理慢或暂停播放导致连接中断
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
}
}