news 2026/6/21 21:38:59

Ubuntu 22.04 下 Nginx-RTMP 高并发直播服务器实战部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 22.04 下 Nginx-RTMP 高并发直播服务器实战部署

1. 为什么是 Nginx-RTMP 而不是 FFmpeg 或其他方案?

在 Ubuntu 22.04 上搭一个能扛住几十路并发推流、同时支持 Web 端低延迟播放的视频服务器,很多人第一反应是“直接用 FFmpeg 转发不就完了?”——我试过,也踩过坑。去年给一家本地教育机构做直播系统时,最初就是用ffmpeg -i rtmp://localhost:1935/live/src -c copy -f flv rtmp://localhost:1935/live/out这种链式转发跑起来的。表面看能用,但第三天就崩了:学生端卡顿率飙升到 40%,后台日志里全是Connection refusedBroken pipe;重启 FFmpeg 后不到两小时又挂;更麻烦的是,一旦要加 HLS 切片、录制回放、多分辨率自适应,就得堆砌七八个 FFmpeg 实例,CPU 占用直冲 98%,htop里密密麻麻全是ffmpeg进程,根本没法监控和限流。

后来我们彻底重做,选了 Nginx-RTMP 模块。不是因为它“新”,而是它把流媒体服务里最硬的几块骨头——连接管理、协议转换、状态跟踪、资源隔离——全压进 Nginx 这个久经考验的事件驱动引擎里。Nginx 本身在 Ubuntu 22.04 上已深度适配 systemd、AppArmor 和内核 TCP 栈优化,而 RTMP 模块只是在其 upstream 机制上做了轻量扩展,不碰主线程模型,也不 fork 子进程。这意味着:单机 2C4G 的 VPS 就能稳稳支撑 80+ 路 RTMP 推流(实测峰值带宽 120 Mbps),HLS 切片延迟稳定在 8–12 秒,且 CPU 峰值长期压在 35% 以下。这不是理论值,是我们在线上跑了 17 个月的真实数据。

关键区别在于架构层级。FFmpeg 是“流处理器”,本质是命令行工具链,它处理的是“一帧一帧的数据”,但不管“谁在连、连了多久、断了几次、带宽多少”。而 Nginx-RTMP 是“流媒体网关”,它天然具备连接上下文:每个 RTMP 客户端连接进来,模块会生成唯一 session ID,记录推流名、时间戳、码率、客户端 IP、User-Agent(如果推流端带了)、甚至首帧 PTS;这些信息全暴露在/stat页面里,还能通过on_publish/on_play回调脚本实时干预。比如我们加了一段 Python 脚本,在on_publish阶段校验推流密钥(从 Redis 读取),非法推流直接拒绝,整个过程耗时 < 8ms,完全不影响推流握手速度。这种能力,FFmpeg 做不到,也没法优雅地做。

再看生态兼容性。Ubuntu 22.04 默认源里的nginx是 1.18 版本,但 Nginx-RTMP 模块要求 Nginx ≥ 1.2.6 且需重新编译。很多人卡在这一步,以为必须手动下载源码、装一堆 dev 包、改 configure 参数。其实大可不必——我们验证过,用 Ubuntu 官方提供的nginx-full包(含所有常用模块)作为基础,仅需 patch 两个小文件就能启用 RTMP,全程不碰./configure。这个细节后面会细说。现在先明确一点:你不是在“装一个流媒体软件”,而是在 Ubuntu 22.04 的成熟 Web 服务底座上,“打开一个流媒体开关”。这个认知差,决定了你是花三天调通,还是花三周反复重装系统。

提示:别被“RTMP 已淘汰”的说法带偏。HLS/DASH 确实更适合公网 CDN 分发,但 RTMP 在局域网推流、OBS 直连、低延迟互动场景仍是事实标准。Nginx-RTMP 不是让你只用 RTMP,而是以 RTMP 为入口,自动转出 HLS、DASH、FLV、甚至 JPEG 截图,它是个协议翻译中枢,不是协议孤岛。

2. 编译前的系统级准备:绕开 Ubuntu 22.04 的三个默认陷阱

Ubuntu 22.04 LTS(Jammy Jellyfish)的底层变化比表面看起来深刻得多。它默认启用systemd-resolved做 DNS 解析,内核升级到 5.15,iptablesnftables全面接管,而最关键的——nginx包从nginx-light/nginx-full拆分为nginx-core+nginx-modules架构。这三点不提前处理,编译 Nginx-RTMP 时会遇到三类典型报错:undefined reference to 'clock_gettime'(链接器找不到实时库)、error: ‘struct sockaddr_storage’ has no member named ‘ss_family’(内核头文件版本错配)、以及最让人抓狂的nginx: [emerg] unknown directive "rtmp"(模块根本没加载成功)。

第一个陷阱:clock_gettime链接失败。Ubuntu 22.04 的libc6-dev默认不链接librt,而 Nginx-RTMP 的ngx_rtmp_cmd_module.c里用了clock_gettime(CLOCK_MONOTONIC, &ts)。解决方法不是加-lrt到 LDFLAGS(那会污染全局),而是精准打补丁:在objs/Makefile生成后、执行make前,用 sed 替换$(LINK) $(LDFLAGS)行,追加-lrt。但更稳妥的做法是,在./configure前设置环境变量:

export LIBS="-lrt" ./configure --add-module=../nginx-rtmp-module --with-http_ssl_module --with-compat

注意,这里--with-compat是关键,它让模块能被动态加载,避免重编译整个 Nginx。我们实测发现,漏掉这个参数,即使编译成功,nginx -t也会报module not found

第二个陷阱:sockaddr_storage成员缺失。这是内核头文件与 Nginx 源码的兼容问题。Ubuntu 22.04 的linux-libc-dev包里,/usr/include/asm-generic/socket.hss_family的定义方式变了。Nginx-RTMP 模块的ngx_rtmp_handler.c第 123 行直接访问((struct sockaddr_storage *)sa)->ss_family,但在新头文件下,ss_family被包裹在联合体里。修复只需一行:把原代码

if (sa->ss_family == AF_INET) {

改成

if (((struct sockaddr_in*)sa)->sin_family == AF_INET) {

——别嫌土,这是最直接有效的绕过方式。我们测试过 12 种 patch 方案,只有这个在 22.04/20.04/18.04 三套系统上全部通过。

第三个陷阱:模块未加载。Ubuntu 22.04 的nginx-full包默认禁用所有第三方模块加载路径。你必须显式配置load_module指令,并确保路径绝对正确。很多教程让你把.so文件丢进/usr/lib/nginx/modules/,但实际路径是/usr/share/nginx/modules/(注意是share不是lib)。更隐蔽的问题是 SELinux/AppArmor 干预:Ubuntu 22.04 默认启用 AppArmor,其abstractions/nginx模板不包含对.so模块的读取权限。临时关闭 AppArmor(sudo systemctl stop apparmor)能快速验证,但生产环境必须加规则:

sudo nano /etc/apparmor.d/local/usr.sbin.nginx # 添加一行: /usr/share/nginx/modules/*.so mr,

然后sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx重载。

最后强调一个易忽略的依赖:libpcre3-dev。Ubuntu 22.04 的pcre2库已成主流,但 Nginx-RTMP 仍依赖老版 PCRE1 的pcre_compile函数。不装libpcre3-dev,configure 会静默跳过 PCRE 支持,导致后续location ~* \.(m3u8|ts)$这类正则匹配全部失效。验证方法很简单:编译完运行nginx -V 2>&1 | grep -o pcre,输出应为pcre而非空。

3. 动态模块编译实战:从零构建可热加载的 rtmp.so

现在进入核心操作。我们放弃“从头编译 Nginx”这种重模式,采用 Ubuntu 22.04 官方nginx-full包 + 动态模块加载的轻量方案。全程无需卸载现有 Nginx,不改动任何系统配置,所有操作在普通用户家目录完成,15 分钟内可完成。

第一步:安装基础依赖并获取源码。注意,这里不用apt install nginx,而是装nginx-full的 dev 包,它包含头文件和静态库:

sudo apt update && sudo apt install -y \ build-essential zlib1g-dev libpcre3-dev libssl-dev \ nginx-full nginx-full-dev git curl wget

nginx-full-dev是关键,它提供/usr/src/nginx/下的完整源码树和debian/rules构建脚本。接着拉取 Nginx-RTMP 模块(用官方主仓库,别用 fork):

cd ~ && git clone https://github.com/arut/nginx-rtmp-module.git

第二步:打上前面提到的两个补丁。先修复sockaddr_storage问题:

sed -i 's/sa->ss_family/((struct sockaddr_in*)sa)->sin_family/g' \ nginx-rtmp-module/ngx_rtmp_handler.c

再修复clock_gettime链接问题,在nginx-rtmp-module/config文件末尾追加:

echo "CORE_LIBS=\"$CORE_LIBS -lrt\"" >> nginx-rtmp-module/config

第三步:利用 Ubuntu 的debian/rules构建系统生成动态模块。这是最省心的方式——它复用官方打包脚本,保证 ABI 兼容:

cd /usr/src/nginx sudo make modules \ MODULES_PATH="/usr/share/nginx/modules" \ MODULES="nginx-rtmp-module" \ MODULES_CONF="debian/modules/nginx-rtmp-module.conf"

注意MODULES_CONF参数指向一个配置文件,我们需提前创建它:

echo "obj-$(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)/nginx-rtmp-module.o" | \ sudo tee /usr/src/nginx/debian/modules/nginx-rtmp-module.conf

执行make modules后,会在/usr/src/nginx/objs/下生成ngx_rtmp_module.so。把它复制到模块目录:

sudo cp /usr/src/nginx/objs/ngx_rtmp_module.so /usr/share/nginx/modules/

第四步:配置 Nginx 加载模块。编辑/etc/nginx/nginx.conf,在user指令下方、events块之前,添加:

load_module /usr/share/nginx/modules/ngx_rtmp_module.so;

然后创建 RTMP 配置文件/etc/nginx/conf.d/rtmp.conf

rtmp { server { listen 1935; chunk_size 4096; application live { live on; record off; allow publish 127.0.0.1; allow publish 192.168.0.0/16; deny publish all; } } }

这里allow publish是安全底线:只允许本机和局域网推流,公网 IP 默认拒绝。别信“先开放再加固”的说法,线上第一行配置就该是防火墙。

第五步:验证模块加载。执行sudo nginx -t,输出必须是syntax is ok且无警告。如果报unknown directive "rtmp",99% 是load_module路径错了或 AppArmor 拦截了。此时运行sudo strace -e trace=openat nginx -t 2>&1 | grep rtmp,能看到 Nginx 实际尝试打开的路径,对照修正即可。

注意:不要用sudo systemctl restart nginx立即生效。先sudo nginx -s reload,它会平滑重启 worker 进程,不中断已有流。我们线上所有更新都走 reload,零秒切换。

4. RTMP→HLS→DASH 全链路配置:不只是“能播”,而是“播得稳”

Nginx-RTMP 的价值不在 RTMP 本身,而在它能把一路推流,实时、无损、低开销地转出多种格式。很多人只配了hls on就以为完工,结果发现 HLS 播放卡顿、切片丢失、DASH manifest 404——问题全出在参数没吃透。

先看 HLS 配置。这是最常用的 Web 播放格式,但默认参数极不友好:

application live { live on; hls on; hls_path /var/www/html/hls; hls_fragment 3s; hls_playlist_length 30s; hls_nested on; }

这段代码有四个致命隐患。第一,hls_path必须是 Nginx worker 进程有写权限的目录,/var/www/html/hls默认属主是www-data,但如果你用sudo nginx -t测试,root 用户能写,worker 却可能因权限不足无法创建文件。解决方案:sudo chown -R www-data:www-data /var/www/html/hls && sudo chmod -R 755 /var/www/html/hls。第二,hls_fragment 3s太短,会导致切片数量爆炸(30 秒 playlist 就要存 10 个.ts文件),磁盘 I/O 压力大,且浏览器缓存效率低。实测5s是平衡点:既保证首屏时间 < 8 秒,又控制文件数在合理范围。第三,hls_playlist_length 30s意味着 m3u8 文件只保留最近 30 秒的索引,但若网络抖动导致某次切片延迟,旧索引被删而新索引未生成,就会出现空白期。我们改为60s,并加hls_cleanup on自动清理过期文件。第四,hls_nested on开启后,切片路径变成hls/streamname/index.m3u8,但很多播放器(如 Video.js)默认不识别嵌套路径,需在 HTML 里显式指定src="hls/streamname/index.m3u8",不如关掉,用扁平路径。

修正后的 HLS 配置:

application live { live on; hls on; hls_path /var/www/html/hls; hls_fragment 5s; hls_playlist_length 60s; hls_cleanup on; hls_nested off; hls_continuous on; # 关键!避免切片间隙 hls_sync 100ms; # 强制音视频 PTS 对齐,防音画不同步 }

再看 DASH。它比 HLS 更复杂,因为需要生成 MPD(Media Presentation Description)文件和分片。Nginx-RTMP 的 DASH 支持是实验性的,但经过我们 11 个月压测,已足够稳定:

application live { live on; dash on; dash_path /var/www/html/dash; dash_fragment 5s; dash_playlist_length 60s; dash_cleanup on; }

注意,DASH 和 HLS 可以共存于同一 application,Nginx 会自动为同一推流生成两套切片。但dash_pathhls_path必须不同目录,否则文件名冲突。DASH 的dash_fragment必须与 HLS 的hls_fragment严格一致,否则 MPD 里的duration字段会错乱,播放器解析失败。我们曾因hls_fragment 5sdash_fragment 4s,导致 dash.js 报Invalid MPD: duration mismatch,排查了 6 小时才发现是这个参数。

最后是 FLV 直播流。很多人忽略它,但它对低延迟场景至关重要:

application live { live on; play /var/www/html/flv; # 指向静态文件目录 }

这行配置让 Nginx-RTMP 开启 HTTP-FLV 服务,URL 为http://your-server/flv?stream=streamname。OBS 或 ffmpeg 可直接用rtmp://your-server/live/streamname推流,前端用 flv.js 播放,端到端延迟压到 1.2 秒以内(实测数据)。flv.js 的优势是纯 JS 实现,不依赖 MSE,兼容 IE11,且启动快。我们对比过 hls.js 和 flv.js:相同网络下,flv.js 首帧时间平均快 2.3 秒,卡顿率低 67%。

提示:所有切片目录(hls_path,dash_path,play目录)必须在 Nginx 配置中显式声明为 location:

location /hls { types { application/vnd.apple.mpegurl m3u8; } root /var/www/html; add_header Cache-Control no-cache; }

否则浏览器会因 MIME 类型错误拒绝加载 m3u8。

5. 生产级加固:从“能跑”到“敢上线”的七道防线

配置完基本功能,离真正上线还差很远。我们总结出七道必须落地的防线,每一道都来自真实故障教训。

第一道:连接数与带宽硬限。Ubuntu 22.04 默认ulimit -n是 1024,Nginx worker 进程最多打开 1024 个文件描述符,而每个 RTMP 连接至少占 3 个 fd(socket、log、hls file),100 路推流就爆了。修改/etc/security/limits.conf

www-data soft nofile 65536 www-data hard nofile 65536

并在/lib/systemd/system/nginx.service[Service]段加:

LimitNOFILE=65536 Restart=on-failure RestartSec=10

然后sudo systemctl daemon-reload && sudo systemctl restart nginx

第二道:推流认证。allow publish只能按 IP 过滤,无法防密码泄露。我们在on_publish回调里集成 JWT 验证:

application live { live on; on_publish http://127.0.0.1:8080/auth; }

后端用 Python Flask 写一个/auth接口,解析 URL 中的?token=xxx,校验签名和有效期,返回200 OK403 Forbidden。Nginx-RTMP 会阻塞推流握手直到回调结束,超时设为 3 秒(on_timeout 3s),避免拖慢正常推流。

第三道:自动录制与归档。教育直播必须存档。record all会录所有流,但磁盘会撑爆。我们用record_unique on生成带时间戳的文件名,并加record_max_size 1G限制单文件大小:

application live { live on; record all; record_path /var/www/html/record; record_suffix -%d-%b-%y-%H-%M-%S.flv; record_unique on; record_max_size 1G; record_interval 3600s; # 每小时切一个文件 }

record_suffix里的%d-%b-%y是日期,%H-%M-%S是时间,生成streamname-01-Jan-23-14-30-22.flv,方便按天归档。

第四道:HTTP 状态页与监控。/stat页面暴露所有连接详情,但默认只允许 127.0.0.1 访问。我们加一层 Basic Auth:

location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; }

openssl passwd -apr1生成密码,存入.htpasswd。这样运维人员可随时查在线人数、码率、延迟。

第五道:日志精细化。默认access_log只记 HTTP 请求,RTMP 推拉流不记录。加rtmp_log指令:

rtmp_log /var/log/nginx/rtmp.log main; log_format main '$remote_addr - $remote_user [$time_local] ' '"$command $app/$flashver" $status $bytes_sent ' '"$session_time" "$bytes_received" "$connect_time"';

$commandpublishplay$session_time是会话时长,$connect_time是握手耗时——这些字段对定位卡顿、断连问题至关重要。

第六道:防火墙白名单。Ubuntu 22.04 默认用ufw,必须精确放行:

sudo ufw allow from 192.168.1.0/24 to any port 1935 # 局域网推流 sudo ufw allow 80/tcp # HTTP sudo ufw allow 443/tcp # HTTPS sudo ufw deny 1935 # 拒绝公网 RTMP

第七道:定期健康检查脚本。我们写了一个check_rtmp.sh,每 5 分钟用curl -I http://localhost/hls/streamname/index.m3u8检查 HLS 是否可访问,失败则发邮件告警。脚本放在/etc/cron.d/,简单有效。

6. 推流与播放端实操:OBS、FFmpeg、Web 三端联调指南

配置再完美,推流和播放端出错也白搭。我们整理出三端最简、最稳的联调方案,覆盖 95% 场景。

OBS Studio 推流(Windows/macOS/Linux 通用)
这是最常用场景。OBS 设置要点:

  • 服务:选择“自定义”
  • 服务器:rtmp://your-server-ip/live(注意结尾是/live,不是/live/streamname
  • 流密钥:填streamname(如class101
  • 关键设置:
    • 视频编码器:x264(别用 NVENC,OBS 28+ 对 NVENC 的 RTMP 封装有 bug)
    • 码率:2500 kbps(1080p)或1200 kbps(720p)
    • 关键帧间隔:2s(必须等于 Nginx 的hls_fragment
    • 预设:veryfast(平衡质量与 CPU)
    • 音频:AAC,码率128 kbps,采样率44.1kHz

推流后,立刻访问http://your-server-ip/stat,看到publish状态为activebytes数字在跳动,说明成功。

FFmpeg 推流(Linux/macOS 终端)
适合自动化或无人值守场景。命令模板:

ffmpeg -re -i /path/to/video.mp4 \ -c:v libx264 -preset veryfast -b:v 2500k -maxrate 2500k \ -g 100 -sc_threshold 0 \ -c:a aac -b:a 128k \ -f flv "rtmp://your-server-ip/live/streamname"

关键参数解释:

  • -re:按原始帧率读取,避免 ffmpeg 疯狂刷帧
  • -g 100:GOP 长度,100 帧 ≈ 2 秒(假设 50fps),必须匹配hls_fragment
  • -sc_threshold 0:禁用场景切换检测,防止 GOP 错乱
  • -maxrate:硬限码率,防突发流量打爆带宽

实测发现,不加-sc_threshold 0,某些 MP4 文件推流后 HLS 切片会频繁中断,日志报hls: fragment not closed

Web 端播放(HTML5 兼容方案)
必须兼顾现代浏览器和老旧设备。我们采用双播放器策略:

  • Chrome/Firefox/Safari:用hls.js播 HLS
  • IE11/Edge Legacy:用flv.js播 HTTP-FLV

HTML 示例:

<div id="video-container"> <video id="video" controls autoplay></video> </div> <script src="https://cdn.jsdelivr.net/npm/hls.js@1.4.2"></script> <script src="https://cdn.jsdelivr.net/npm/flv.js@1.8.2"></script> <script> const video = document.getElementById('video'); const streamName = 'streamname'; let hls, flv; // 检测 HLS 支持 if (Hls.isSupported()) { hls = new Hls(); hls.loadSource(`http://your-server/hls/${streamName}/index.m3u8`); hls.attachMedia(video); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { // Safari 原生 HLS video.src = `http://your-server/hls/${streamName}/index.m3u8`; } else { // 降级到 FLV flv = flvjs.createPlayer({ type: 'flv', url: `http://your-server/flv?stream=${streamName}`, isLive: true, enableStatis: false, }); flv.attachMediaElement(video); flv.load(); } </script>

注意enableStatis: false关闭统计上报,减少额外请求。isLive: true启用直播模式,自动处理追帧。

最后分享一个血泪经验:所有播放 URL 必须用http://,别用https://,除非你已配好 TLS 证书。Nginx-RTMP 的 HLS 输出不支持 HTTPS 重定向,浏览器会直接报Mixed Content错误。我们曾因在开发环境用http,上线后切https却忘了改播放地址,导致全站直播黑屏 2 小时。

7. 故障排查黄金链路:从“播不了”到“根因定位”的完整路径

线上最怕的不是报错,而是“一切看似正常,但就是播不了”。我们梳理出一条标准化排查链路,按顺序执行,90% 的问题 10 分钟内定位。

第一步:确认 Nginx-RTMP 模块已加载
执行sudo nginx -V 2>&1 | grep -o rtmp,输出应为rtmp。若为空,检查load_module路径和 AppArmor 权限。

第二步:检查 RTMP 端口是否监听

sudo ss -tlnp | grep :1935

应看到nginx: master process。若无输出,检查rtmp { server { listen 1935; } }是否在配置中,且nginx -t通过。

第三步:验证推流是否到达 Nginx
tcpdump抓包:

sudo tcpdump -i any -nn port 1935 -w rtmp.pcap

推流 10 秒后停止,用 Wireshark 打开rtmp.pcap,过滤rtmp,应看到connectcreateStreampublish等握手包。若只有connect没有publish,说明推流端被allow publish拦截。

第四步:检查 HLS 切片是否生成

ls -la /var/www/html/hls/streamname/

应有index.m3u8和若干*.ts文件。若无,检查hls_path权限和hls on是否开启。

第五步:验证 m3u8 文件内容

curl http://your-server/hls/streamname/index.m3u8

输出应为标准 m3u8 格式,包含#EXTINF:5.000,streamname-xxxx.ts。若返回 404,检查 Nginx 的location /hls配置和 MIME 类型。

第六步:用 VLC 直播测试
VLC 是终极验证工具:

  • 打开 VLC → 媒体 → 打开网络串流 → 输入rtmp://your-server/live/streamname
  • 若能播,说明 RTMP 正常;再输http://your-server/hls/streamname/index.m3u8,若能播,说明 HLS 正常。VLC 不受浏览器 CORS 限制,是排除前端问题的利器。

第七步:分析 Nginx 日志
重点看/var/log/nginx/error.log

  • client denied by ruleallow publish规则拒绝
  • hls: fragment not closed:GOP 设置错误
  • stat: failed to open filehls_path权限不足
  • on_publish timeout:认证接口响应超时

我们曾遇到一个诡异问题:error.log里大量hls: fragment not closed,但hls_fragment明明设了 5s。最终发现是推流端(OBS)的keyframe interval设成了0,导致 GOP 不固定。把 OBS 的关键帧间隔从0改成2s,问题消失。

提示:所有排查步骤必须按顺序执行,跳步只会浪费时间。我们内部 SOP 规定,运维接到“播不了”告警,必须严格走完这七步,每步截图留痕。不是为了甩锅,而是让问题可追溯、可复现、可沉淀。

8. 性能压测与容量规划:单机到底能扛多少路流?

“能跑”和“能扛”是两回事。我们用真实压测数据告诉你 Ubuntu 22.04 上 Nginx-RTMP 的真实边界。

测试环境:

  • 云服务器:2 核 4G,SSD 磁盘,100 Mbps 带宽
  • 推流端:10 台机器,每台用 FFmpeg 循环推 720p@1200kbps 视频
  • 播放端:200 个 Chrome 标签页,用 hls.js 播放同一index.m3u8

压测结果:

并发推流路数CPU 使用率内存占用HLS 延迟切片丢失率
2022%1.1G7.2s0%
5048%1.8G8.1s0.02%
8076%2.9G9.5s0.15%
10092%3.7G12.3s1.8%

关键发现:

  • 瓶颈在磁盘 I/O,不在 CPU。当推流 > 60 路时,iostat -x 1显示await(平均等待时间)从 1ms 升至 15ms,%util达 98%。这是因为每个.ts文件写入都是小 IO,HLS 切片频率高,SSD 也扛不住。解决方案:把hls_path挂载到内存盘(tmpfs):

    sudo mount -t tmpfs -o size=2G tmpfs /var/www/html/hls sudo chown -R www-data:www-data /var/www/html/hls

    压测后,100 路时await降至 0.3ms,延迟稳定在 8.5s,丢失率归零。

  • 带宽不是线性增长。100 路 1200kbps 推流,理论带宽 120 Mbps,但实测出口带宽仅 85 Mbps。原因是 Nginx-RTMP 的 HLS 转码有压缩冗余,且 TCP 传输有开销。我们按“理论带宽 × 0.7”做容量规划,留足缓冲。

  • 连接数有隐性上限。Ubuntu 22.04 的net.core.somaxconn默认 128,当并发连接 > 100 时,新连接会排队。需调大:

    echo 'net.core.somaxconn = 4096' | sudo tee -a /etc/sysctl.conf sudo sysctl -p

容量规划公式:

所需服务器数 = ceil(总推流路数 × 1.2 / 单机安全路数)

其中单机安全路数 = 60(H

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/21 21:29:13

TPU协处理器PMA函数:飞轮齿信号同步与角度解码实战解析

1. 项目概述&#xff1a;TPU与PMA函数在飞轮齿信号处理中的核心价值在汽车发动机控制、工业电机位置检测等嵌入式实时系统中&#xff0c;处理高速、高精度的脉冲序列信号是一项基础且关键的任务。想象一下&#xff0c;你需要通过一个带有36个均匀齿和1个特殊“缺齿”或“多齿”…

作者头像 李华
网站建设 2026/6/21 21:25:32

终极指南:DDrawCompat如何让Windows经典游戏在现代系统重生

终极指南&#xff1a;DDrawCompat如何让Windows经典游戏在现代系统重生 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirrors/dd/D…

作者头像 李华
网站建设 2026/6/21 21:20:48

Ubuntu 18.04 创建带sudo权限的普通用户完整指南

1. 项目概述&#xff1a;在 Ubuntu 18.04 上安全创建具备 sudo 权限的普通用户你刚装好一台 Ubuntu 18.04 服务器或开发机&#xff0c;系统默认只给了 root 用户&#xff08;或者安装时设置的那个初始用户&#xff09;sudo 权限。现在你要给团队新成员、测试环境里的隔离账户&a…

作者头像 李华