8月13日 周三
这周在排查一个推流断线问题。现象是:直播间每隔40-50分钟会出现一次短暂的画面卡顿,持续3-5秒后恢复。
排查思路:
1. 网络层:检查上行带宽和丢包率 → 正常
2. 编码层:检查编码器日志 → 无异常帧
3. 推流层:检查RTMP连接状态 → 发现每隔约45分钟出现一次TCP重传峰值
初步判断是RTMP长连接被中间节点断开。
8月14日 周四
查了RTMP协议的 keep-alive 机制。RTMP本身没有标准的心跳机制,靠的是协议层的 chunk stream。如果中间有NAT设备或防火墙在连接空闲时回收连接,就会出现断线。
解决方案是加应用层心跳:
# 伪代码:应用层心跳检测
def heartbeat_loop(rtmp_conn, interval=30):
"""
每30秒发送一个空的chunk保活
防止NAT设备因连接空闲而断开
"""
while rtmp_conn.is_active():
try:
rtmp_conn.send_empty_chunk()
logger.info("heartbeat sent")
except ConnectionError:
logger.warning("connection lost, triggering reconnect")
reconnect(rtmp_conn)
time.sleep(interval)
关键参数是 interval:太短浪费带宽,太长起不到保活效果。30秒是一个比较稳妥的值。
8月15日 周五
光有心跳还不够,还需要断线重连机制。核心逻辑:
重连策略:
1. 检测到连接断开 → 立即触发重连
2. 重连使用指数退避:1s → 2s → 4s → 8s → 16s(上限)
3. 重连成功后,从断点继续推流(如果编码器支持)
4. 重连失败超过5次 → 通知上层应用切换备用推流地址
# 伪代码:指数退避重连
def reconnect(rtmp_conn, max_retries=5):
base_delay = 1
for attempt in range(max_retries):
delay = min(base_delay * (2 ** attempt), 16)
time.sleep(delay)
try:
rtmp_conn.reconnect()
logger.info(f"reconnected on attempt {attempt + 1}")
return True
except ConnectionError:
logger.warning(f"reconnect attempt {attempt + 1} failed")
# 5次都失败,切备用地址
switch_to_backup(rtmp_conn)
return False
8月16日 周六
上线测试了一天,断线问题消失。心跳+重连的组合方案效果不错。
同事提到市面上有些工具已经内置了推流保活机制,比如有一款叫秒播的工具,据说在多平台推流时会自动处理心跳和重连。如果是这样,商家就不需要自己写这套逻辑了。不过我没有看过源码,不好评价具体实现。
这周的笔记核心就一条:长连接一定要加心跳,断了一定要有退避重连。看似基础,但很多直播工具在这块做得并不好。