背景
當存在一個推流客戶端正在向rtmp://xxx.com/live/yyy推流時,又有另外一個推流客戶端同時對這個地址進行推流,會發生什麼呢?
查閱了 Adobe RTMP Spec 發現規範本身並未說明和定義這個場景下RTMP伺服器應該怎麼處理。
最近在實際工作中遇到部分客戶對推流地址資源管理不恰當而導致重複推流報錯的問題,且在查問題的過程中發現各個CDN廠商對“搶流”的處理各不相同,查閱相關文件說明發現資料甚少,故專門對它們的搶流行為做如下分析。
搶流:指對同個地址資源進行重複推流
步驟
- 開啟Wireshark捕獲網路卡,過濾規則:
tcp && tcp.port == 1935
(之所以不直接寫rtmpt
是因為還想觀察傳輸層的行為) - 獲取對應廠商的推拉流URL,假設推流地址是:
rtmp://xxx.com/live/yyy
- 使用
ffmpeg
推送一個本地電影檔案:ffmpeg -re -i Movie-1.flv -vcodec h264 -f flv "rtmp://xxx.com/live/yyy"
- 使用另一個
ffmpeg
推送另一個本地電影檔案到同個URL:ffmpeg -re -i Movie-2.flv -vcodec h264 -f flv "rtmp://xxx.com/live/yyy"
- 使用
ffplay
播放拉流地址內容 - 觀察現象並分析Wireshark抓包結果
廠商
資料
注:下列結果僅代表發表本文的時候的各CDN廠家行為,隨著廠商對伺服器的更新迭代,可能會有所改變。
廠商 | 現象 | 結論 | 官方文件說明 | 與文件描述一致 |
---|---|---|---|---|
網宿 | 二次推流報錯,ffplay 拉流播放的是Movie-1內容 |
抓包分析發現第二次推流的RTMP連線能握手成功,但是publish() 請求發出之後伺服器應答onStatus('NetStream.Publish.BadName') (見參考文件) |
直播推流與拉流 | ✔️ |
阿里雲 | 二次推流報錯,ffplay 拉流播放的是Movie-1內容 |
抓包分析發現第二次推流的RTMP連線能握手成功,但是推流幾秒之後CDN伺服器會發來TCP RST包強制斷開RTMP的TCP連線 | 未找到 | ❓ |
騰訊雲 | 二次推流成功,ffplay 拉流播放的是Movie-1內容關閉第一個推流的程式,播放內容變成Movie-2的內容 |
官方文件表明會拒絕第二個推流請求,但是實際實驗下來竟然是可以重複推且不報錯,不知道騰訊雲這麼實現有沒有其他用意 | 推流失敗問題排查 | ❌ |
七牛雲 | 二次推流報錯,ffplay 拉流播放的是Movie-1內容 |
RTMP能握手成功,但是推流幾秒之後伺服器會發來TCP RST包強制斷開RTMP的TCP連線 與官方文件中提到的後者擠掉前者的說法不一致 |
推流不成功的原因和解決方法 | ❌ |
金山雲 | 二次推流報錯,ffplay 拉流播放的是Movie-1內容 |
抓包分析發現第二次推流的RTMP連線能握手成功,但是publish() 請求發出之後伺服器應答onStatus('NetStream.Publish.AlreadyExistStreamName') (見參考文件) |
推拉流接入 | ✔️ |
結論
總的來說,按當前實驗結果來看,在這種細枝末節的功能點上,金山雲的文件說明最清晰最規範,點個贊!
網宿的行為符合Flash AS3
的定義,至少有據可依。
而騰訊雲與七牛雲的文件說明均存在錯誤的地方(至少本次實驗中是這樣的),尤其是騰訊雲的現象讓我很意外。
而阿里雲竟然連這塊的文件都沒有。。(也許是我沒搜到,若有的話望指正)