视频播放–带宽挤占故障排查与限流方案-Nginx

阅读对象:后端 / 运维开发人员
核心目标:搞懂「应用层限流」和「操作系统网卡限流」的本质区别,理解为什么 Nginx 限流治标不治本,什么场景下要用底层流量整形

一、基础环境梳理(先理清拓扑)

1.1 服务器资源分布

服务器操作系统Web 服务承载业务
LinuxNginxOA 业务、ERP 业务、AI 中台、视频教学(流量暴增来源)
Windows ServerIIS文件管理、统一认证、图片管理

1.2 网络约束

两台服务器共用一条物理网线,总出口带宽固定 20M

关键点:带宽是共享资源,一旦视频业务跑满整条链路,两台机器所有业务、远程桌面 / SSH 全部都会卡顿。

二、故障现象描述

用户访问【视频教学】并发突增 → Linux 服务器占用几乎全部 20M 带宽
连锁影响:

  1. Linux 上 OA、ERP、AI 中台网站访问缓慢

  2. Windows Server 上 IIS 部署的统一认证、文件管理、图片管理访问超时

  3. 两台服务器远程管理连接延迟高、掉线

三、排查思考过程(运维排查思路完整记录)

Step1:先定位流量到底来自哪一台服务器

思考:带宽被占满,第一步不能直接改配置限流,先定位流量来源主机

  • Windows 服务器:使用 GlassWire 进程级流量监控工具,观察出站流量

  • Linux 服务器:使用 nethogs 按进程查看流量消耗

排查结果确认:流量峰值全部来自 Linux 服务器的 Nginx 进程,大量 mp4 视频请求

初步判断:mp4 视频文件下载 / 播放请求过大,吃掉全部公网带宽。接下来思考:可以从哪几层做限速?
可选方案分层:

  1. Nginx(应用层)做访问频率、单 IP 速度、并发连接限制

  2. Linux 操作系统内核层(TC 流量控制)对网卡 / 端口硬性带宽封顶

  3. 网络设备层面(交换机 / 防火墙)做带宽划分

四、方案 1:Nginx 单 IP 局部限流(第一次尝试)

4.1 设计思路

思考逻辑:限制单个客户端 IP 的请求频率和并发连接,防止一个用户多线程拉视频占满带宽。
使用 nginx limit_conn_zone 按客户端 IP 做连接池;limit_req_zone 限制每秒请求次数。

配置代码片段:

# 以客户端真实IP作为key,开辟共享内存区域
limit_conn_zone $binary_remote_addr zone=mp4_conn:10m;
limit_req_zone $binary_remote_addr zone=mp4_req:10m rate=5r/s ;

4.2 实施效果

执行 nginx -s reload 重载配置后短暂改善;清理缓存后仅稳定约 30 分钟
当访问量再次冲高,请求不断堆积排队,带宽再次跑满,故障复现。

4.3 失败原因思考(核心知识点)

  1. 该规则只限制单一个 IP,无法控制所有用户加起来的总带宽

  2. 大量不同用户同时播放视频,每个 IP 都没有超过限制,但是整体流量叠加依然打满 20M 带宽

  3. 视频支持断点续传(Range 分片请求),同一个视频会拆成几十条小请求,绕过简单的请求频率限制

结论:单 IP 限流 ≠ 整机出口带宽控制

五、方案 2:Nginx 增加全局共享限流(第二次优化尝试)

5.1 优化思考

上一轮只限制单个用户不行 → 增加全局共享令牌池,针对站点整体限制总并发、总请求速率;
同时增加 limit_rate 单文件下载限速、长缓存策略减少重复请求。

完整配置:

# 单用户限流池
limit_conn_zone $binary_remote_addr zone=mp4_conn:10m;
limit_req_zone $binary_remote_addr zone=mp4_req:10m rate=5r/s ;

# 全局共享限流池(所有访客共用一套配额)
limit_conn_zone $server_name zone=mp4_conn_global:10m;
limit_req_zone $server_name zone=mp4_req_global:10m rate=10r/s;

location ~* \.mp4$ {
    # 单客户端限制
    limit_conn mp4_conn 5;
    limit_req zone=mp4_req burst=8 nodelay;
    limit_rate 200k;
    limit_rate_after 1m;

    expires 2d;
    add_header Cache-Control public;
    add_header Accept-Ranges bytes;
    error_page 503 = @rate_limit;

    # 全站视频全局配额
    limit_conn mp4_conn_global 15;
    limit_req zone=mp4_req_global burst=20 nodelay;
}

5.2 实际效果

配置重载后短期缓解;流量持续上涨一段时间后,请求队列持续积压,带宽再次跑满,卡顿问题重现。

5.3 深度原理复盘(技术科普重点)

  1. limit_conn / limit_req 管控的是HTTP 连接数、请求个数,不是网卡出站比特流(带宽)

  2. limit_rate 是单连接限速,但大量并发连接叠加之后,总的出口流量依然可以突破预期带宽

  3. Nginx 属于应用层软件控制,请求到达 Nginx 之后才做拦截;数据包已经占用了系统网络开销

  4. 断点续传、多 Range 分片播放会产生大量短连接,很容易耗尽配置中的 burst 令牌池,限流规则提前被击穿

一句话总结:Nginx 限流只能控制 HTTP 业务逻辑,不能真正锁死服务器网卡的最大出口带宽

六、方案 3:Linux TC 网卡内核级流量整形(底层限速方案)

6.1 方案思考

既然应用层无法严格控制整机带宽,我们下沉到操作系统内核网卡层面做流量管控。
使用 Linux TC(Traffic Control)HTB 分层令牌桶队列,直接在网卡 em1 上对 8041 端口出站流量硬性封顶带宽。

执行脚本:

export DEV=em1
# 清除历史旧的流量控制规则
tc qdisc del dev $DEV root
# 创建根队列
tc qdisc add dev $DEV root handle 1:0 htb default 10
# 设置带宽上限:10Mbit,封顶10M,不可突破
tc class add dev $DEV parent 1:0 classid 1:10 htb rate 10mbit ceil 10mbit prio 1
# 过滤源端口8041的流量,绑定到限速队列
tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 match ip sport 8041 0xffff flowid 1:10

6.2 原理科普给研发理解

  1. TC 工作在 Linux 内核协议栈,数据包发送出去之前就被内核限速

  2. HTB 队列可以硬性锁定某个业务最大占用带宽,物理网卡流量不会超过设定值

  3. 20M 总带宽拆分:视频业务封顶 10M,剩下 10M 带宽留给 OA/ERP/AI 中台 + Windows 服务器所有业务

  4. 优先级机制可以保障非视频业务在带宽紧张时优先通行

6.3 当前待验证点

TC 命令是临时生效,重启服务器规则丢失;需要做成开机自启脚本,配合监控持续观测带宽水位。

七、三层限流技术对比表(科普总结)

限流方案工作层级控制对象优点缺点
Nginx limit_conn / limit_req应用层 (HTTP)请求数、并发连接配置灵活,可以返回 503 提示,区分用户无法严格控制整机带宽,分片下载容易击穿
Nginx limit_rate应用层 (文件流)单连接下载速度限制单个视频下载速度多并发叠加依然跑满带宽
Linux TC HTB操作系统内核网卡层网卡真实出站带宽 (Mbit)硬性带宽封顶,从底层保护整条链路控制粒度是端口 / IP,业务友好提示弱,配置复杂

八、整体问题根因总结(技术知识点沉淀)

  1. 共享带宽架构缺陷:多业务、多服务器共用一条 20M 链路,没有带宽隔离,单业务峰值直接影响全部系统

  2. 应用层限流 ≠ 带宽限流:Nginx 是 Web 服务,只管理 HTTP 请求,管不住网卡真实的比特流

  3. 视频业务天然属于大流量长连接业务,单纯依靠 Web 层面的请求计数限流效果有限

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐