香港服务器如何设置和优化利用大带宽 + CN2 GIA 线路,解决跨境直播观众的延迟与卡顿?

香港 MEGA-i 的风太“干净”,半夜两点我从冷气里醒过来,手机微信工作群炸了——华东、华南的观众在直播间刷“卡”“转圈圈”。我们的跨境直播主链路当时还跑在常规国际回程上,晚高峰抖得厉害。我当下做了两个决定:
- 把直播跨境回程切到 CN2 GIA。
- 把服务器从“能跑”调到“能扛”,尤其是低时延 + 稳吞吐这组矛盾要同时达成。
这篇文章,就是那一夜以及之后两周我在香港机房把这件事做“顺”的全过程复盘。
目标与方案总览
目标:大陆观众(跨境)观看香港源站直播,首帧快、卡顿少、回放稳定。
核心手段:香港机房 大带宽(≥10Gbps) + CN2 GIA 低时延优先回程,配合协议层优化(SRT/RTMP + LL-HLS)、内核/网卡调优、BGP/策略路由、转码与 ABR 梯度设计、监控与回源熔断/CDN 旁路。
拓扑(简图)
主播(OBS/SRT/RTMP)
│ (公网)
▼
[香港接入层] Nginx(HTTP/3)/SRS(RTMP+SRT) + FFmpeg转码
│ 10GbE →→→
▼
[香港边界路由器] eBGP: CN2 GIA(AS4809) + 备份国际(AS2914/AS3491)
│ 选路: 中国去CN2、高优先级;全球去备份
▼
观众端播放器(LL-HLS/HTTP-FLV/SRT 拉流)
物理与基础设施:我用的“真家伙”
机型与硬件参数(两种典型形态)
| 角色 | 方案 A:高密转码节点(GPU) | 方案 B:轻量接入/边缘 |
|---|---|---|
| CPU | AMD EPYC 7313P(16C/32T,3.0GHz) | Intel E-2288G(8C/16T,5GHz 单核强) |
| 内存 | 128GB ECC | 64GB ECC |
| 存储 | 2 × 1.92TB NVMe(RAID1,元数据+切片缓存) | 2 × 960GB NVMe(RAID1) |
| GPU | NVIDIA T4 × 1(NVENC) | 无(纯 CPU x264) |
| 网卡 | Intel X710 10GbE × 2(bonding) | Intel i210 1GbE × 2 |
| OS | CentOS 7.9(内核升级至 kernel-ml ≥ 5.15 以启用 BBRv2 稳定) | 同 |
| 带宽 | CN2 GIA 专线 10Gbps(95th 计费),全球备份 5Gbps | CN2 GIA 2Gbps |
理由:转码节点 GPU NVENC 在相同画质下能省 3~5 倍 CPU,10GbE 是为了峰值与并发;X710 在多队列、RSS、offload、PPS 稳定性上比千兆卡更友好。
线路与机房要点
- CN2 GIA:对内地回程时延更稳,AS 主要识别 AS4809(电信 CN2),对 AS4134/4837/9808 等国内网运营商走优先策略。
- 备份国际:选一家口碑好且与香港互联紧密的上游(如 AS2914 NTT、AS3491 PCCW 等)做路由兜底。
- IPv6 全面开:CN2 GIA v6 对部分省份的握手时延更好,看你观众画像决定是否在播放器默认优先 v6。
网络与内核:把“通道”先打通、打稳
环境:CentOS 7.9 + kernel-ml(ELRepo) + X710 驱动 ixgbe/ice(视版本)
1) 升级内核 & 启用 BBR(或 BBRv2)
# ELRepo 安装主线内核
sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
sudo yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
sudo yum --enablerepo=elrepo-kernel install -y kernel-ml
# 设置默认内核为 kernel-ml
sudo grub2-set-default 0 && sudo grub2-mkconfig -o /boot/grub2/grub.cfg
reboot
/etc/sysctl.d/99-net.conf(直播/低时延优化基线)
# 队列与缓冲
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.netdev_max_backlog = 250000
net.core.somaxconn = 65535
# TCP 窗口
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.ipv4.tcp_notsent_lowat = 16384
# 拥塞控制与队列
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# Fast Open(观众端 HTTP/TLS)
net.ipv4.tcp_fastopen = 3
# TIME-WAIT 回收不建议打开,避免 NAT/中间盒问题
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 0
# 连接跟踪容量(HTTP/LL-HLS 多连接)
net.netfilter.nf_conntrack_max = 2621440
sudo sysctl --system
经验:直播下行面向“长连接 + 连续吞吐”,BBR 相比 CUBIC 对“高时延×中等丢包”的跨境链路更稳;HTTP 侧用 fq 队列均衡突发,降低“秒级抖动”。
2) 网卡与中断亲和(X710 为例)
# 查看多队列
ethtool -l eth0
# 调整 ring buffer
ethtool -G eth0 rx 4096 tx 4096
# 关闭/开启硬件 offload(保持 GRO on,LRO off 更安全)
ethtool -K eth0 tso on gso on gro on lro off rx on tx on
# 绑定中断到不同 CPU 核,减少抖动
grep eth0-TxRx /proc/interrupts
# 假设中断号 123,124,125,126
echo 1 > /proc/irq/123/smp_affinity # 绑核0
echo 2 > /proc/irq/124/smp_affinity # 绑核1
echo 4 > /proc/irq/125/smp_affinity # 绑核2
echo 8 > /proc/irq/126/smp_affinity # 绑核3
# RPS/XPS
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo f > /sys/class/net/eth0/queues/tx-0/xps_cpus
踩坑:曾经把 LRO 开着导致 HTTP-FLV 的时延抖动上升(黏包重组过度)。关掉 LRO、保留 GRO 后,尾延(p95)下降约 12–18ms。
3) 轻量整形(避免“挤爆”对端)
直播时上游或观众侧路由器缓冲“炸裂”会抖。给出口做 90–95% 线速整形 + FQ:
# 以 9Gbps 整形 10Gbps 口
tc qdisc replace dev eth0 root fq maxrate 9gbit
BGP 与 CN2 GIA:让“中国去中国的路”
我们在边界用 FRRouting(frr)做 eBGP,策略是:来自/去往中国的前缀走 CN2 GIA(AS4809)优先,其余目的地走备份国际。
FRR 关键片段(简化示例)
/etc/frr/daemons:开启 bgpd
bgpd=yes
/etc/frr/frr.conf(示意)
router bgp 65001
bgp router-id 203.0.113.1
bgp log-neighbor-changes
neighbor 198.51.100.1 remote-as 4809 ! CN2 GIA
neighbor 203.0.113.9 remote-as 2914 ! 备份国际
! 入站:来自中国 ASN 的路由提升 LocalPref
ip as-path access-list CHINA-AS permit _4134_|_4809_|_4837_|_9808_
route-map CN-IN permit 10
match as-path CHINA-AS
set local-preference 300
route-map CN-IN permit 20
! 入站默认
route-map INTL-IN permit 10
set local-preference 200
! 绑定入站策略
neighbor 198.51.100.1 route-map CN-IN in
neighbor 203.0.113.9 route-map INTL-IN in
! 出站:对中国前缀优先对 CN2 广播(可结合社区/LP)
ip prefix-list OUR-PUB permit 203.0.113.0/24
route-map OUT-CN permit 10
match ip address prefix-list OUR-PUB
set community 4809:9999 additive
!
address-family ipv4 unicast
network 203.0.113.0/24
neighbor 198.51.100.1 activate
neighbor 203.0.113.9 activate
neighbor 198.51.100.1 route-map OUT-CN out
exit-address-family
注:与上游确认可用的社区标记(有些提供“仅向电信/联通宣告”或“优先级”社区),不同运营商社区不同。若上游不支持社区策略,也能依靠 LocalPref + MED 做入站/出站偏好。
流媒体协议与服务:我落地的“组合拳”
选择与兼容
- 推流(主播 → 源站):SRT(更抗抖丢)优先,RTMP 兼容。
- 出流(源站 → 观众):LL-HLS(Safari/移动端友好) + HTTP-FLV(PC Web 低延迟)并行,必要时保留 WebRTC(超低延),但成本高。
- 转码:GPU NVENC(T4)或 CPU x264 ultrafast。
- ABR 梯度(关键帧 2s 对齐):1080p 6Mbps、720p 3Mbps、480p 1.2Mbps、360p 800Kbps。
SRS(Simple Realtime Server)作为接入核心
安装(CentOS 7)
yum install -y git gcc gcc-c++ make automake autoconf cmake openssl-devel
git clone https://github.com/ossrs/srs.git && cd srs/trunk
./configure --full --prefix=/usr/local/srs
make -j && make install
/usr/local/srs/conf/srs.conf(关键片段)
listen 1935; # RTMP
max_connections 20000;
daemon on;
srs_log_tank file;
srs_log_file /var/log/srs.log;
# 推流认证(示例)
http_api {
enabled on;
listen 1985;
}
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
tcp_nodelay on;
# SRT 接入(外置 srt-live-server 亦可)
ingest srt_in {
enabled off; # 若用内部模块则 on,亦可用独立 srt-live-transmit
}
# RTMP 推流
publish {
mr on;
mr_latency 100;
}
# HLS(LL-HLS 由前置 Nginx 处理切片与 HTTP/3)
hls {
enabled on;
hls_fragment 1; # 1s 片
hls_window 6; # 低延迟窗口
hls_path /data/hls;
hls_cleanup on;
}
# HTTP-FLV
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
}
经验:SRS 的 mr/mr_latency 对 RTMP 推流端抖动有明显缓冲作用;HLS 片长拉到 1s 是 LL-HLS 的基础,但必须确保转码关键帧间隔=2s 并与分片对齐。
FFmpeg 转码(GPU 与 CPU 两套)
GPU(T4/NVENC)
ffmpeg -hwaccel cuda -y -i rtmp://127.0.0.1/live/stream \
-c:v h264_nvenc -preset p3 -profile:v high -g 48 -keyint_min 48 -sc_threshold 0 -b:v 6M -maxrate 6.5M -bufsize 13M -f hls -hls_time 1 -hls_list_size 6 -hls_flags delete_segments+append_list /data/hls/1080p.m3u8 \
-c:v h264_nvenc -preset p3 -profile:v high -g 48 -keyint_min 48 -b:v 3M -maxrate 3.2M -bufsize 6M -f hls -hls_time 1 -hls_list_size 6 -hls_flags delete_segments+append_list /data/hls/720p.m3u8 \
-c:v h264_nvenc -preset p3 -profile:v main -g 48 -keyint_min 48 -b:v 1200k -maxrate 1400k -bufsize 2400k -f hls -hls_time 1 -hls_list_size 6 -hls_flags delete_segments+append_list /data/hls/480p.m3u8 \
-c:a aac -b:a 128k
CPU(x264)
ffmpeg -y -i rtmp://127.0.0.1/live/stream \
-c:v libx264 -preset ultrafast -tune zerolatency -profile:v high -g 48 -keyint_min 48 -sc_threshold 0 -b:v 6M ...(同上各档) \
-c:a aac -b:a 128k
Nginx(前置) + HTTP/3(可选)
CentOS 7 上我更倾向 OpenResty(稳定)+ BoringSSL/Quiche 自编译开 HTTP/3。如果嫌编译重,先用 HTTP/2,收益已足够可观。
nginx.conf(HLS/HTTP-FLV 关键)
worker_processes auto;
worker_rlimit_nofile 200000;
events {
worker_connections 65535;
multi_accept on;
use epoll;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
aio on;
# TLS/HTTP2/3 略...
# gzip/etag/缓存控制略...
server {
listen 80 default_server reuseport;
# listen 443 ssl http2 reuseport; # 若启 HTTPS
server_name _;
# LL-HLS 切片
location /hls/ {
types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
add_header Cache-Control "no-cache";
add_header Access-Control-Allow-Origin *;
root /data;
}
# HTTP-FLV
location ~ \.flv$ {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://127.0.0.1:8080; # SRS http_server
}
}
}
坑:worker_rlimit_nofile 与 worker_connections 不够会先“隐性丢连接”。配套需要把系统 nofile 拉到 ≥ 200k,并同步调整 ulimit -n。
播放器与 ABR:参数要“对齐”
- GOP/关键帧 = 2s(48 帧 @ 24fps / 60 帧 @ 30fps),分片 1s 必须对齐关键帧。
- 目标首帧 ≤ 1.2s,稳定延迟(LL-HLS)在 2~4s。
- ABR 逻辑:上报下载时延、丢包、缓冲长度,按 p95 平滑切档,避免抖动频繁升降。
- HTTP/2/3:长连接与头压缩能降低“每段”握手损耗;TLS 做 Session Resumption/Tickets,OCSP Stapling。
监控、压测与可观测
- 网络:mtr(观众省份回程跟踪)、smokeping(时延/抖动趋势)、iperf3(上下行基准)。
- 服务:Prometheus Node Exporter、Nginx/SRS Exporter,自建 Grafana 仪表。
- 端到端:播放器埋点(首帧时间、卡顿比、平均码率、切档次数、重连率)。
示例埋点(关键字段)
| 指标 | 说明 |
|---|---|
startup_time_ms |
从点击到首帧 |
rebuffer_ratio |
卡顿时间 / 播放时长 |
avg_play_bitrate |
平均播放码率 |
stall_events |
卡顿次数 |
tcp_rtt_ms |
TCP RTT 估计 |
http3_used |
HTTP/3 命中率 |
“真场景”前后对比数据(节选)
注:以下为一次晚高峰专项优化后的实测节选(示例)
| 地区 | 方案前(国际常规) p95 RTT | 方案后(CN2 GIA) p95 RTT | 卡顿比例(前→后) | 首帧(前→后) |
|---|---|---|---|---|
| 华东(上海) | 85 ms | 43 ms | 2.9% → 0.8% | 2.1s → 1.0s |
| 华南(广东) | 68 ms | 36 ms | 2.1% → 0.6% | 1.8s → 0.9s |
| 华北(北京) | 98 ms | 55 ms | 3.4% → 1.1% | 2.3s → 1.2s |
现场“坑与解法”:我真遇到过的
晚高峰上行“尖刺”:主播端偶发突发导致源站 tx 突刺,观众抖。
解法:tc fq maxrate=0.9×线速 限突发 + SRS mr_latency=100,抖动明显收敛。
LRO/GRO 配置不当:HTTP-FLV 尾延拉长。
解法:保持 GRO on / LRO off,并校准 rx/tx ring 到 4096。
BBR 初期超前:个别省份上游中间盒对 BBR 行为不友好,初始突发丢包。
解法:fq + maxrate 限制,或在该线路策略性回落 CUBIC(少数流)。
文件句柄打爆:LL-HLS + HTTP/2 多并发拉高 fd。
解法:系统 nofile、Nginx worker_rlimit_nofile、SRS max_connections 一并提升并压测校核。
BGP 路由“回国绕路”:某运营商晚高峰切国际备份导致回程波动。
解法:与上游确认 社区,下发“对中宣告优先/仅宣告”社区;必要时做策略路由对特定 ASN 强制走 CN2 邻居。
TLS 握手开销:大量短连接(播放器频繁拉 m3u8/ts)。
解法:强推 HTTP/2/3,打开 Session Resumption,保证证书链轻量,开启 OCSP Stapling。
安全与合规“底线”
- WAF/Rate Limit:对 /hls/*.m3u8、/*.ts 做 IP 维度速率限制与黑名单;对推流接口加签名与时效。
- SSH 只允许跳板机 + 密钥登陆,Fail2ban 处理异常重试。
- 合规提醒:跨境分发/落地需符合当地与中国大陆的相关政策与牌照要求,务必在业务前期与法务确认。本文仅讨论技术实现。
从零到上线:我给团队的“落地清单”(CentOS 7)
机房与链路:
- 申请 CN2 GIA 10G 上下行(95th 或固定带宽),备份国际 5G。
- 要到 BGP 社区手册、IPv4/v6 地址、LOA。
系统与网络:
- 升级 kernel-ml,按文中 sysctl、ethtool、irq 亲和、RPS/XPS 调优。
- tc fq maxrate=0.9× 线速整形。
BGP:
- FRR 建立与 GIA/备份的 eBGP 会话;按 ASN 匹配策略提升中国去向。
- 演练上游故障与收敛时间。
流媒体栈:
- SRS + Nginx 前置,配置 RTMP/SRT 接入、LL-HLS 与 HTTP-FLV。
- FFmpeg 转码(优先 NVENC),GOP=2s、分片=1s 对齐。
监控:
- mtr/smokeping、Prometheus + Grafana、播放器埋点。
- 告警阈值:startup_time_ms、rebuffer_ratio、BGP flap、NIC 丢包。
压测与灰度:
- 观众典型省份节点选取进行 拨测;
- 按 10%、30%、100% 流量逐级切到 CN2 GIA。
预案:
- 上游 GIA 故障自动降级至备份国际 + 播放器缓冲上调;
- 播放器侧 ABR 保守策略开关(晚高峰)。
附:一页式参数“抄作业表”
| 模块 | 关键参数 | 建议值 |
|---|---|---|
| OS | kernel | ELRepo kernel-ml ≥ 5.15 |
| TCP | 拥塞控制 | bbr |
| qdisc | 出口 | fq maxrate=0.9×线速 |
| NIC | ring | rx/tx = 4096 |
| NIC | offload | GRO on / LRO off / TSO,GSO on |
| BGP | 中国 ASN | `4134 |
| HLS | 分片 | 1s |
| 编码 | GOP | 2s,-g 与 -keyint_min 对齐 |
| ABR | 档位 | 1080p 6M / 720p 3M / 480p 1.2M / 360p 800K |
| 连接 | nofile | ≥ 200k(系统与 Nginx) |
| 监控 | 关键 KPI | 首帧、卡顿比、p95 RTT、切档次数 |
把最后一条 BGP 社区下发出去,我在机房过道坐了十分钟。Grafana 的曲线像被人按住了一样平了下来,群里开始刷“不卡了”“清晰不少”。凌晨三点,MEGA-i 的灯很白、很静。我合上笔记本,给自己记下了这份 checklist。
后来每当有伙伴问我:“跨境直播要怎么从‘能用’跑到‘稳定’?”
把路走对(CN2 GIA),把栈搭好(SRT/LL-HLS/ABR),把内核和网卡拧到位,然后用数据去证伪每一次犹疑。
你会发现,“不卡”,不是一句口号,是无数个小参数、小策略叠出来的确定性。