本篇文章給大家帶來的內容是關于如何理解基于nginx-rtmp-module模塊實現的http-FLV直播模塊nginx-http-flv-module,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
目前已經有很多個人和廠商準備將本模塊商用,據網友反饋,國外已經有直播網站在用這個模塊。準備商用的廠商中最著名的是華為,網友和廠商陸續反饋過不少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數量和輸出計入,現已添加?,F在對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),因為之前已經進行過鑒權了?,F在將本地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編譯工程失?。ㄔ诰W上查了一下,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