基於nginx-rtmp-module模塊實現的HTTP-FLV直播模塊nginx-http-flv-module(二)

      由於《基於nginx-rtmp-module模塊實現的HTTP-FLV直播模塊nginx-http-flv-module(一)》內容已經很長,所以後續的更新將記錄在這兒。非常感謝網友們的測試反饋和代碼提交!項目地址:https://github.com/winshining/nginx-http-flv-module。有問題或者建議,可以加Q羣:711969608詳聊。目前已經有很多個人和廠商準備將本模塊商用,據網友反饋,國外已經有直播網站在用這個模塊。準備商用的廠商中最著名的是華爲,網友和廠商陸續反饋過不少bug,修復後功能已經越來越穩定,在此表示感謝。

2018-06-04:一家CDN廠商正式上線nginx-http-flv-module,使用RTMP方式,開gop_cache配置(關閉interleave配置,打開會卡頓或者沒有聲音,目前暫時不知如何修復),他們的客戶包括映客和微吼。

2018-06-28:一家網絡視頻廠商正式上線nginx-http-flv-module,使用HTTP-FLV方式,不開gop_cache配置,目前還沒開全量,等待觀察穩定性。

2018-07-28:應一部分網友的需求,已經提供RHEL6(CentOS 6)和RHEL7(CentOS 7)的rpm安裝包,見nginx-http-flv-module-packages

        nginx-http-flv-module與nginx-rtmp-module的功能對比:

功能 nginx-http-flv-module nginx-rtmp-module 備註
HTTP-FLV × nginx-http-flv-module支持HTTPS-FLV
GOP緩存 ×  
vhost ×  
省略listen配置 x

 

JSON風格的stat x  
RTMP 302 Beta × nginx-http-flv-module作爲服務器或者客戶端

2018-03-09更新:

最近這段時間主要在不同平臺測試模塊的穩定性,目前播放這一塊沒發現問題,由於條件限制,除了FreeBSD平臺沒測試過,Windows 7,Debian 7.x和macOS Sierra都測試過了,由於Nginx官方對Windows支持不太好,沒用Windows平臺最強大的IOCP接口(使用的select),所以導致Windows平臺上運行效率不太高,表現在推流等待時間長,3s+,首屏時間很長,4s+,select本身原因限制客戶端個數,默認是1024。推流等待時間和首屏時間最短的是macOS Sierra,本機上測試時基本上是秒推秒開。昨晚專門注意了一下,在macOS Sierra下編譯時,SO_REUSEPORT和TCP_FASTOPEN兩項都支持,前者讓Nginx的每個子進程都可以listen,都有一個專門的accept隊列,解決了驚羣效應;後者則是在發起SYN時就已經攜帶實際數據,而不是握手完畢後再傳輸實際數據。秒推秒開可能跟這兩個選項有關。但是macOS Sierra並不支持將某個進程綁定到某個CPU上,所以可能進程上下文切換會有開銷,系統負載較大時可能效率不如Linux。由於macOS Sierra是公司的電腦,所以未做壓力測試。我的筆記本裝的是Debian 7.x,因爲內核版本較低,所以macOS Sierra上支持的兩個選項都不支持。測試時推流等待時間和首屏時間都介於Windows 7和macOS Sierra之間,在服務器上測試時(系統CentOS 6.4,支持SO_REUSEPORT但是不支持TCP_FASTOPEN)跟macOS Sierra上差不多,但是考慮到服務器的CPU性能強大得多,所以負載不高情況下,macOS Sierra的表現是最好的。由於macOS Sierra是從Mac OS X更新來的,而Mac OS X的底層最初是在FreeBSD基礎上開發的,所以推測在FreeBSD上的表現應該也不錯。

另外最近在嘗試添加RTMP 302重定向轉HTTP 302重定向的功能,由於很多播放器不支持RTMP 302重定向,但是支持HTTP 302重定向的功能基本上是標配,實測VLC是支持的。目前功能基本上已經完成,但是困擾的地方還是使用HTTP框架的發送接口時,鏈表在長時間播放後會形成環,所以進展不下去了,沒有更新到github上。下面是nginx的rtmp主要配置片段和VLC播放時的HTTP 302重定向截圖:其中推流是在名爲hls的application上推的(FFmpeg也不支持RTMP 302重定向,所以只能往hls推)。

application myapp {

    ...;

    rewrite '^/myapp/(.*)' '/hsl/$1';

}

 

1.HTTP 302重定向抓包簡略圖

 

2.HTTP 302重定向抓包詳情圖

2018-03-15更新:

有網友反饋on_play指令不能使用,經調試,是因爲加入的ngx_http_flv_live模塊的順序有問題,現修改爲不改變模塊順序的前提下,經過一些狀態的修改繞過它,後續再調用其中的一些函數,以保證與原來的nginx-rtmp-module的功能一致。

2018-03-16更新:

部分網友們提出的CORS(跨域)功能已經可用,HTTP-FLV的回覆數據不再使用硬編碼,而是使用部分HTTP框架的代碼重寫了。另外,on_connect功能有問題,暫時不能用,等待修復。

2018-03-18更新:

on_connect的問題已經修復。

2018-03-20更新:

修復因爲要查找的application不在第一個server塊中造成找不到對應的on_connect和on_play的bug,經查是由於沒有匹配到正確的server配置,已修復。

2018-03-22更新:

很久之前有網友提出過設置idle_streams爲off(默認爲on)時,使用HTTP-FLV方式播pull會失敗,現已修復。

2018-03-25更新:

有網友使用flv.js播放nginx-http-flv-module拉的直播流,發現一個bug:當(1)使用的Nginx版本號爲1.13.9,(2)播放器爲flv.js,(3)播放pull的流時,會出現無法播放的情況,經查是因爲flv.js發送了HTTP頭“Connection: keep-alive”,nginx-http-flv-module在向上遊發起請求時,下游請求一般在上游請求還沒有返回時就已經返回,但是Nginx從版本1.13.1起,刪除了一個r->blocked判斷,而“Connection: keep-alive”導致ngx_http_finalize_request調用ngx_http_set_keepalive,這個函數會調用註冊的cleanup函數來關閉下游的請求,導致播放失敗。已經修復。也正是在調試這個bug的過程中,發現nginx-http-flv-module在打開gop_cache配置項的情況下,flv.js跟其他主流的播放器(如vlc)相比,首屏時間是最快的,幾乎沒有延遲,使用的pull源是香港衛視的直播源:rtmp://live.hkstv.hk.lxdns.com/live/hks

2018-03-27更新:

順手改點代碼就有bug,真是惱火。最近爲了響應一些網友要求添加定製的HTTP頭的功能,修改了發送功能,再次嘗試將Nginx的HTTP框架的filter接口引入,還是失敗了,所以簡單粗暴地把最後一個filter模塊和header_filter模塊挑出來,刪除了很多用不上的代碼。github上編譯用的是Nginx官方的穩定版本nginx-1.12.2。結果今天有網友反饋編譯不過去,經查剛好這幾個找不到的宏是在我從修改nginx-rtmp-module就一直使用的nginx-1.11.10中加入的,而網友用的版本低一些就編譯不過去,已經修復。

2018-03-29更新:

前幾天有網友反饋使用nginx-1.13.1以及以上的版本與nginx-http-flv-module一起編譯時,使用flv.js播放pull流會失敗,見2018-03-25更新,結果修復了那個問題,又出了先推流,然後使用flv.js播放會失敗的問題,真是隨手改出bug,問題已經修復,最新版本的Nginx和稍微舊一些的版本(nginx-1.11.10)都已經測試通過。

2018-04-05記錄:

這次不是更新:)昨天有網友反饋使用flv.js播放推流時,一直播放不了,我還以爲nginx-http-flv-module又出問題了,自己測試了一下,用最新的nginx-1.13.10一起編譯,播放推流和拉流都沒問題,又用官方的穩定版nginx-1.12.2一起編譯,還是沒問題,晚上準備看看哪兒出問題的時候,網友反饋是瀏覽器限制了flv.js的數量,他用的是Chrome,據測試單瀏覽器只能開6個flv.js,今天中午我用Firefox測試了一下,也是同樣的問題,第7個flv.js播放不了,然後開VLC播放,沒有問題,由此可以確認不是nginx-http-flv-module的問題。不過這是個很重要的信息,瀏覽器對flv.js的播放支持是有數量限制的,Chrome和Firefox的限制數量都是6個,其他瀏覽器未測試。

2018-04-06更新:

之前的統計數據一直沒有把http-flv直播的accepted數量和輸出計入,現已添加。現在對flv.js的支持已經穩定,下面是使用flv.js播放的截圖:

一個商用廠商反饋視頻源是純視頻時,不管使用什麼播放器,播放連接沒問題,但是一直接收不到視頻數據,經調試發現是因爲判斷純音頻的邏輯有bug,導致nginx-http-flv-module在發送音視頻數據的接口中無限循環了,現已修復。

2018-04-14更新:

有網友昨天反饋開啓gop_cache選項時,推流會導致內存泄露,已查明是推流關閉時沒有釋放gop cache模塊分配的內存造成的,已修復。另外,據網友反饋,多進程模式下,on_connect和on_play指令有問題,暫時別在多進程模式下用這兩個指令,等待修復。

2018-04-15更新:

一個商用廠商反饋隨機閃斷測試時,內存會不斷增長,懷疑有內存泄露,晚上調試時確認確實有內存泄露,是由於沒有釋放ngx_http_request_t結構中的內存池造成的,已修復。

2018-04-21更新:

有網友反饋多進程模式下,使用on_play進行鑑權操作,但是在推流的時候,本地relay(接受推流的子進程將流推給別的子進程)也會執行on_play鑑權,這是不太合理的(但是其實並不算bug),因爲之前已經進行過鑑權了。現在將本地relay的on_play操作去掉了,nginx-http-flv-module並不關心on_play用來做什麼,但是考慮到本地relay不應該再執行on_play操作了,修改的代碼也比較簡單,恢復也很容易,所以先暫時這樣修改。另外網友@qqzzzx 反饋的壓測崩潰的問題已經修復一部分,現在還存在的問題是壓測羣斷後會有內存泄露的問題,修復後會更新到github上。

2018-04-25更新:

壓力測試崩潰的問題已經修復,捎帶解決了可能出現的CPU使用率過高的問題,已壓力測試1個多小時(srs-bench自帶的測試視頻,500路HTTP-FLV和200路RTMP),暫未發現問題,歡迎反饋bug。

2018-05-12更新:

有網友反饋開啓gop_cache選項,某些情況下壓力測試會特別耗費內存,不確定是不是有內存泄露。壓測多次不能復現,網友提示壓測工具和服務器不在同一主機上比較容易復現。按照這種方式壓測果然比較容易復現,但是出現耗費內存比較大的情況下,停止壓力測試,然後再次壓力測試且併發數不變,內存不會增長,證明不是內存泄露的問題。後來反覆查看源代碼後,猜想是因爲發送GOP的時候,一次性將GOP數據放入發送環形數組中,由於Nginx是異步非阻塞的,所以Nginx不一定會馬上將數據從環形數組中真正發送到網絡(如服務器和客戶端之間的網絡帶寬不足的情況下),造成已分配的內存不能馬上循環使用,而且真正發送完GOP後,已分配的內存不再釋放(在內存池中,並且與連接無關,只跟配置結構體有關)。後續的數據傳輸不像GOP數據是一次性全部發送,所以導致回收的內存不能被充分使用,有很大一部分閒置了。現將gop cache模塊修改爲使用自己獨立的內存池,等GOP發送完後,釋放這個內存池。

2018-05-14更新:

修復了一個2018-05-12更新引入的內存泄露的bug,屬於代碼久了看不懂,然後一改就出問題的情況抓狂。修復高版本gcc編譯工程失敗(在網上查了一下,gcc-7.x.x在添加了某些編譯選項時,會檢查switch的case是否有fall through)的bug,不過我手頭沒有很高版本的gcc,所以可能還存在一些沒被發現的編譯錯誤,目前正等待網友的回覆。

2018-05-16更新:

白天編譯安裝了gcc-7.2.0,找出了所有的fall through編譯警告(Nginx的編譯選項中被視爲錯誤),已修復bug。

2018-05-18記錄:

這次不是更新,2018-05-12更新中我猜想壓力測試(使用的工具是srs-bench)時開啓gop_cache選項會特別耗費內存的原因,今晚經過查看日誌,發現之前的猜想其實不是主要原因。從日誌中可以看到Nginx在接收數據時一直都是128字節,而在配置中如果沒有指明chunk_size配置項時,默認是4096個字節,就是說服務器發送Set Chunk Size協議控制消息後,客戶端並沒有響應Set Chunk Size協議控制消息,所以服務器一直沿用之前的128字節,最糟糕的情況下,會導致nginx-http-flv-module在接收到數據後,分配內存對數據進行打包時,用(4096+RTMP頭最大大小)這麼多字節的空間來打包128字節的數據,白白浪費了32倍多的數據。使用ffmpeg進行對比測試,ffmpeg是會響應Set Chunk Size協議控制消息的,所以不會造成內存浪費。已經給SRS(Simple-RTMP-Server)的作者提issue了。後續有空我會更新nginx-http-flv-module對這種異常的處理。

2018-05-20更新:

某些情況下特別耗費內存的問題已經修復,如果耗費使用量還很大,那麼可能是由上面說的那個次要原因引起的了。

2018-06-14更新:

修復一個網友反饋的問題,ngx_stat_active參數在運行一段時間後值不正確,經查是由於重複減去操作造成的,已修復,不影響正常功能使用。

2018-06-19更新:

同步了幾個nginx-rtmp-module的pull requests裏的bug修復,基本上都是一些很明顯的bug,大的修改沒同步過來。另外,目前在nginx-http-flv-module基礎上添加了直接推送fmp4的功能,今晚已經實現直接推送純視頻的fmp4到支持MSE(Media Source Extensions,目前iOS上的Safari不支持)的瀏覽器中播放,後續會將音頻一起加上。

2018-06-25更新:

推送fmp4的基本功能已經基本完成。有網友推了支持JSON格式的stat的PR,已經合併,試用了下,感覺非常不錯,另外修復了一個小bug。

2018-06-29更新:

將stat中原有的rtmp信息修改爲http-flv,鑑於已經有兩個廠商分別正式商用RTMP(開啓gop_cache)和HTTP-FLV(不開gop_cache),發佈了里程碑版本1.2.4。

2018-07-09更新:

修復了3個小bug:開啓DASH功能時,有可能因爲從文件中讀取的數據爲0導致無限循環;修復xml方式的stat中不能顯示nginx-http-flv-module的版本號的問題(網友的PR);修復HEAD請求沒有配置flv_live的locations時返回405(Method Not Allowed)的bug。

2018-07-20更新:

修復了一個日誌記錄bug,剛好把client和server對調了。

2018-07-30更新:

修復一個潛在的導致內存泄露的問題和一個與nginx-1.15.2編譯出錯(高版本的Linux內核支持SO_REUSEPORT(詳情見2018-03-09更新),nginx-1.15.2修改了一個函數的參數類型)的問題。

其他文章:

基於nginx-rtmp-module模塊實現的HTTP-FLV直播模塊nginx-http-flv-module(一)

基於nginx-rtmp-module模塊實現的HTTP-FLV直播模塊nginx-http-flv-module(三)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章