上一篇 下一篇 分享链接 返回 返回顶部

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

发布人:Minchunlin 发布时间:2025-09-09 09:43 阅读量:1083


香港 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 做入站/出站偏好。

流媒体协议与服务:我落地的“组合拳”

选择与兼容

  1. 推流(主播 → 源站):SRT(更抗抖丢)优先,RTMP 兼容。
  2. 出流(源站 → 观众):LL-HLS(Safari/移动端友好) + HTTP-FLV(PC Web 低延迟)并行,必要时保留 WebRTC(超低延),但成本高。
  3. 转码:GPU NVENC(T4)或 CPU x264 ultrafast。
  4. 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),把内核和网卡拧到位,然后用数据去证伪每一次犹疑。

你会发现,“不卡”,不是一句口号,是无数个小参数、小策略叠出来的确定性。

目录结构
全文