在实战中使用nginx-rtmp遇到的TCP连接问题分析

简介: 在实战中使用nginx-rtmp遇到的TCP连接问题分析 背景 前段时间公司做了一次体育赛事的现场直播,网络由某通信公司负责搭建,主要测试5G CPE上行网络的带宽和稳定性,为了做到万无一失,他们同时搭建了一条用作备份的400M光纤线路。

在实战中使用nginx-rtmp遇到的TCP连接问题分析

背景

前段时间公司做了一次体育赛事的现场直播,网络由某通信公司负责搭建,主要测试5G CPE上行网络的带宽和稳定性,为了做到万无一失,他们同时搭建了一条用作备份的400M光纤线路。通过配置交换机来做到主备切换,要达到以下的效果:

  • 无线链路down掉,交换机自动检测到丢包,丢包到指定数量(可以在交换机中配置),自动切换到备用链路。
  • 无线链接恢复,备用链路切换回无线链路。

参考 静态路由与SLA技术

我们采用nginx-rtmp搭建了2层CDN。

测试

推流端推送RTMP流会向nginx-rtmp发送请求建立TCP链接,推流过程中,把交换机上的无线链路网线拔掉。自动切换到光纤线路,推流端重连后依然不能够成功建立链接,推流软件卡死。

server端的TCP链接一直存在:

root@iz2zehy7gff0ksipgb4ch3z /u/l/nginx# netstat -natp | grep "1936"
tcp        0      0 0.0.0.0:1936            0.0.0.0:*               LISTEN      9467/nginx: master  
tcp        0      0 192.168.199.6:1936      223.71.3.82:46012       ESTABLISHED 11177/nginx: worker 

nginx 报错了:

 
2019/05/20 15:44:58 [error] 6947#0: *286 live: already publishing, client: 223.71.3.82, server: 0.0.0.0:1936

此时

就是因为无线链接断开时,TCP链接不能够被正常关闭,publisher会一直存在导致的。

复习一下四次挥手:

我们知道TCP连接有一个特性:

TCP 连接一旦建立,只要通信双方之间的中间结点(包括网关和交换机、路由器等网络设备)工作正常,那么在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。TCP 连接的这种特性,使得一个长期不交换任何信息的空闲连接可以长期保持数小时、数天甚至数月。中间路由器可以崩溃、重启,网线可以被挂断再连通,只要两端的主机没有被重启,TCP 连接就可以被一直保持下来。

可以看到,网线虽然断掉了,但是server端没有收到client的任何消息,server端不会主动发起挥手,因此连接会一直维持很长一段时间(我的测试机器上大概数小时)。链接断开后server端一直在发送PSH+ACK:

如何才能实现快速重连

为源站加load balance

加一个备源和一个调度服务,调度策略采取轮询,两次连续的TCP连接请求会被定向到不同的源站上面。这个方法治标不治本,切一次可以,如果无线链路恢复,再切回来的时候,可能TCP链接还没有关闭。

添加drop_idle_publisher

Syntax: drop_idle_publisher timeout
Context: rtmp, server, application

Drop publisher connection which has been idle (no audio/video data) within specified time. Default is off. Note this only works when connection is in publish mode (after sending publish command).

drop_idle_publisher 10s;

nginx-rtmp会在指定的时间内丢弃空闲的publisher:

root@iz2zehy7gff0ksipgb4ch3z /u/l/n/logs# netstat -natp | grep "1936"
tcp        0      0 0.0.0.0:1936            0.0.0.0:*               LISTEN      11421/nginx: master 
tcp        0      0 192.168.199.6:1936      61.148.243.150:9338     ESTABLISHED 12923/nginx: worker 
tcp        0      1 192.168.199.6:1936      223.71.3.82:47240       FIN_WAIT1   -      

可见这次是server端在2s后探测到这个TCP连接处于空闲状态,主动发起了挥手消息,此时publisher就被释放掉了,再次推流会重新建立新的TCP,重新生成此publisher。

上图是链路断掉后,TCP链接完全断开前server端向client发送的数据包,可以看到一直在发送FIN+最后一个数据包的ACK,时间间隔大概为 0.2秒->0.4秒->0.8秒->1.6秒->3.2秒->6.4秒->12.8秒->25.6秒

这种方法是可行的。

so_keepalive

listen

syntax: listen (addr[:port]|port|unix:path) [bind] [ipv6only=on|off] [so_keepalive=on|off|keepidle:keepintvl:keepcnt|proxy_protocol]

context: server

Adds listening socket to NGINX for accepting RTMP connections

关于TCP探活机制的几个参数的说明:

  • keepcnt 关闭一个非活跃连接之前进行探测的最大次数t
  • keepidle 对一个连接进行有效性探测之前运行的最大非活跃时间间隔
  • keepintvl 两个探测的时间间隔

设置如下参数:

listen 1936 so_keepalive=5s:2:2; 

可以看到,最后一个ACK没有回复后隔了5秒开始TCP keep-alive 探活,总共两次,间隔2秒,最后发送RST+ACK断开了TCP连接 。

参考

nginx-rtmp-module wiki

TCP 连接断连问题剖析

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
5月前
|
负载均衡 网络协议 算法
Nginx系列教程(13) - TCP反向代理实现
Nginx系列教程(13) - TCP反向代理实现
400 0
|
6月前
|
网络协议 应用服务中间件 nginx
nginx配置tcp协议代理的日志
nginx配置tcp协议代理的日志
145 0
|
3月前
|
负载均衡 网络协议 小程序
Nginx配置Tcp负载均衡
Nginx配置Tcp负载均衡
|
3月前
|
网络协议 关系型数据库 MySQL
【nginx】使用nginx转发tcp请求
【nginx】使用nginx转发tcp请求
106 1
|
8月前
|
网络协议 架构师 应用服务中间件
Nginx 实战系列之三:Nginx TCP backlog 分析优化和性能相关经验汇总
Nginx 实战系列之三:Nginx TCP backlog 分析优化和性能相关经验汇总
|
9月前
|
网络协议 应用服务中间件 nginx
Nginx TCP 端口转发
Nginx TCP 端口转发
128 0
|
缓存 网络协议 网络架构
四十、TCP协议的特点、TCP报文段格式和TCP的连接管理
四十、TCP协议的特点、TCP报文段格式和TCP的连接管理
四十、TCP协议的特点、TCP报文段格式和TCP的连接管理
|
网络协议
计算机网络学习27:TCP连接与连接释放
客户端和服务端都是先建立传输控制模块
计算机网络学习27:TCP连接与连接释放
|
网络协议
Flutter TCP连接
Flutter TCP连接
|
缓存 网络协议 Java
在项目中使用Curator的Java 客户端搭建后进行长TCP连接和TCP权限配置【Zookeeper】
在项目中使用Curator的Java 客户端搭建后进行长TCP连接和TCP权限配置【Zookeeper】
257 0
在项目中使用Curator的Java 客户端搭建后进行长TCP连接和TCP权限配置【Zookeeper】