视频流代理:从 Java 到 Nginx 的性能优化实践
数据归集系统的视频流代理(FLV/HLS)由 Java Controller 实现,每路视频流占用一个 Tomcat 线程做 8KB 缓冲区转发。并发路数多时会耗尽线程池。本文记录了将 FLV 代理迁移到 Nginx 的完整方案,以及 HLS 仍需走 Java 代理的技术原因。
🎧 文章导读
🎵 背景音乐
背景
水文监测系统需要播放 Lisa 视频平台的实时监控视频。后端通过反向代理解决前端无法直接访问内网视频流的问题。
原有实现是纯 Java 方案:
1 | 前端 → Java(play接口) → FLV/HLS 都返回 Java 代理地址 |
问题:每路视频流占用一个 Tomcat 线程,做 8KB 缓冲区转发。当同时播放 20 路视频时,Tomcat 线程池压力很大。
方案设计

图1:Java 代理模式 vs Nginx 代理模式的架构对比
新增 Nginx 流代理,与 Java 代理并存,通过配置切换:
1 | 【Nginx 代理模式】(新增,生产环境推荐) |
关键决策:FLV 走 Nginx,HLS 走 Java。
为什么 HLS 不能走 Nginx?
Nginx 是纯透传代理,无法改写 M3U8 文件中的 TS 片段路径。Lisa 平台 M3U8 中的 TS 为相对路径,经 Nginx 代理后 HLS.js 解析出的 TS 地址没有 url 参数,请求会失败。
1 | Lisa 原始 M3U8: |
Java 代理会改写 M3U8 内容,将 TS 地址替换为 Java 代理地址:
1 | 改写后的 M3U8: |
为什么 FLV 可以走 Nginx?
FLV 是单条连续流,不需要改写内容,Nginx 透传完全没问题。而且 FLV 才是长时间占用 Tomcat 线程的大头(一个摄像头可能持续播放几小时)。
Nginx 配置
1 | server { |
关键配置说明:
| 配置项 | 作用 |
|---|---|
proxy_buffering off |
关闭缓冲,实时转发视频流 |
proxy_read_timeout 3600s |
长连接超时 1 小时 |
set $target $arg_url |
从查询参数动态获取代理目标 |
resolver |
DNS 解析器,用于解析 $target 中的域名 |
Java 代码改动
修改 LisaVideoServiceImpl.java 的 rewriteUrls() 方法,根据配置决定 FLV 的代理目标:
1 |
|
配置项
| 配置项 | 值 | 说明 |
|---|---|---|
lisa.video.proxy-type |
nginx 或 java |
决定 FLV 走 Nginx 还是 Java,默认 java |
lisa.video.proxy-base-url |
http://10.144.32.219:9223 |
Java 代理地址 |
lisa.video.nginx-base-url |
http://10.144.32.219:18001 |
Nginx 代理地址 |
切换方式:修改 Consul 配置 lisa.video.proxy-type=nginx,重启或热更新即可。
验证步骤
阶段一:Nginx 代理单独验证
- 部署 Nginx 配置,确认 18001 端口可访问
- 调 play 接口拿一个上游 FLV 地址
- 直接访问
http://nginx:18001/video-proxy/?url=<上游flv地址>,确认返回video/x-flv流
阶段二:Java 配置切换验证
- Consul 配置
lisa.video.proxy-type=nginx - 重启 Java 服务
- 调用
POST /dataCollection/video/play,确认返回的 FLV URL 指向 Nginx,HLS URL 指向 Java - 用 flv.js 播放 FLV 验证
- 用 hls.js 播放 HLS 验证
阶段三:回退验证
- Consul 改回
lisa.video.proxy-type=java - 确认 FLV 和 HLS 都恢复为 Java 代理模式
风险点
| 风险 | 应对 |
|---|---|
| Nginx DNS 解析器配置不对 | 根据服务器环境配置正确的 resolver,或直接用 IP |
| Nginx 未部署或端口不通 | proxy-type 保持 java,不影响现有功能 |
| Nginx 无 host 白名单(开放代理) | 内网环境风险低;如需加固,可在 Nginx 层加 if 校验 |
性能对比

图2:Java 代理 vs Nginx 代理的性能指标对比
| 指标 | Java 代理 | Nginx 代理 |
|---|---|---|
| 每路视频占用 | 1 个 Tomcat 线程 | Nginx worker 连接 |
| 内存开销 | 8KB 缓冲区 × 并发数 | 极低 |
| 最大并发路数 | 受 Tomcat 线程池限制(默认 200) | 数千路 |
| CPU 开销 | 较高(Java 内存拷贝) | 极低(内核态转发) |
经验总结
- Nginx 适合纯透传场景——不需要改写内容的代理(如 FLV)交给 Nginx,需要改写内容的(如 HLS M3U8)留在 Java
- 配置切换比代码部署更灵活——通过 Consul 配置
proxy-type可以随时切换代理模式,不需要重新部署 - 视频流代理要关闭缓冲——
proxy_buffering off是关键配置,否则 Nginx 会缓冲整个视频再返回 - 超时时间要足够长——视频流可能持续几小时,
proxy_read_timeout要设为 3600s 或更长
本文涉及文件:LisaVideoServiceImpl.java、Nginx 配置、Consul 配置。