摘要:年月日,社區聯合又拍云,舉辦全國巡回沙龍北京站,京東云技術專家羅玉杰在活動上做了在直播場景中的應用的分享。項目功能基于協議將文件上傳至云存儲。
2019 年 3 月 23 日,OpenResty 社區聯合又拍云,舉辦 OpenResty × Open Talk 全國巡回沙龍·北京站,京東云技術專家羅玉杰在活動上做了《 OpenResty 在直播場景中的應用 》的分享。
OpenResty x Open Talk 全國巡回沙龍是由 OpenResty 社區、又拍云發起,邀請業內資深的 OpenResty 技術專家,分享 OpenResty 實戰經驗,增進 OpenResty 使用者的交流與學習,推動 OpenResty 開源項目的發展。活動已經在深圳、北京兩地舉辦,未來將陸續在武漢、上海、杭州、成都等城市巡回舉辦。
羅玉杰,京東云技術專家,10 余年 CDN、流媒體行業從業經驗,熱衷于開源軟件的開發與研究,對 OpenResty、Nginx 模塊開發有較深入的研究,熟悉 CDN 架構和主流流媒體協議。
以下是分享全文:
大家下午好,我是來自京東云的羅玉杰,今天給大家分享的主題是 《OpenResty 在直播場景中的應用》。
項目需求京東云前期的服務是基于 Nginx 二次開發的,之后因為要對接上云的需求,于是新做了兩個服務,一個是對接云存儲的上傳服務,另一個是偏業務層的直播時移回看服務。項目的需求是做視頻數據上云,主要是視頻的相關數據對接云存儲,需求的開發周期很緊,基本上是以周為單位。
我們之前的服務用 C 、C++ 開發,但 C 和 C++ 的開發周期很長。我們發現這個項目基于 OpenResty 開發是非常適合的,可以極大地縮短開發周期,同時提高運行效率,并且 OpenResty 對運維非常友好,能提供很多的配置項,讓運維根據線上動態修改一些配置,甚至運維都可以看懂代碼的主流程。
項目體系結構
上圖是一個直播服務的主流體系結構,先是主播基于 RTMP 協議推到 CDN 邊緣,接著到視頻源站接入層,然后把 RTMP 流推送到切片上傳服務器,上面有兩個服務:一個是切片服務,把流式的視頻流進行切片存儲到本地,生成 TS 視頻文件和 M3U8 文本文件,每形成一個小切片都會通知上傳服務,后者將這些 TS 文件和 M3U8 文件基于 AWS S3 協議上傳到云存儲服務,我們的云存儲兼容 AWS S3 協議。在此基礎上,我們用 OpenResty 做了一個直播時移回看服務,用戶基于 HLS 協議看視頻,請求參數里帶上時間段信息,比如幾天之前或者幾個小時之前的信息,此服務從云存儲上下載 M3U8 信息進行裁剪,再返回給用戶,用戶就可以看到視頻了。HLS 協議的應用面、支持面很廣,各大廠商、終端支持得都非常好,而且對 HTTP 和 CDN 原有的技術棧、體系非常友好,可以充分地利用原來的一些積累。有的播放是基于 RTMP,HDL(HTTP + FLV)協議的,需要播放器的支持。
1、基于 s3 PUT 協議將 TS 文件上傳至云存儲。
2、S3 multi 分片上傳大文件,支持斷點續傳。這個服務重度依賴于 Redis,用 Redis 實現任務隊列、存儲任務元數據、點播 M3U8。
3、基于 Redis 實現任務隊列的同時做了 Nginx Worker 的負載調度。在此基礎上做了對于后端服務的保護,連接和請求量控制,防止被短時間內特別大的突發流量把后端的云服務直接打垮。實現任務隊列之后,對后端的鏈接數是固定的,而且請求處理看的是后端服務的能力,簡單地說,它處理得多快就請求得多快。
4、為了保證云和服務的高可靠性,我們做了失敗重試和異常處理、降低策略。其中,任務失敗是不可避免的,現在也遇到了大量的任務失敗,包括鏈接失敗、后端服務異常等,需要把失敗的任務進行重試,降級。把它在失敗隊列里面,進行一些指數退避。還有一些降級策略,我這個服務依賴于后面的 Redis 服務,和后端的云存儲服務,如果它們失敗之后,我們需要做一些功能的降級,保證我們的服務高可用。在后端 Redis 服務恢復的時候再把數據同步過去,保證數據不會丟失。
5、還有就是生成直播、點播 M38,為后續的服務提供一些基礎數據。如直播時移回看服務。
AWS S3 協議
AWS S3 比較復雜的就是鑒權,主要用它的兩個協議,一個是 PUT,一個是 MULTI PART。
AWS S3 的鑒權和 Nginx 中的 Secure Link 模塊比較相似,將請求相關信息用私鑰做一個散列,這個散列的內容會放到 HTTP 頭 authorization 里面,服務端收到請求后,會有同樣的方式和同樣的私鑰來計算這個內容,計算出的內容是相同的就會通過,不相同的話會認為是一個非法請求。
它主要分三步驟,第一步是創建任務,創建任務之后會返回一個 ID 當做任務的 Session ID,用 POST 和 REST 規范實現的協議。初始化任務之后,可以傳各種分片了,然后還是用 PUT 傳小片,加上 Session ID,每一片都是這樣。
上傳任務成功之后,會發一個 Complete 消息,然后文件就認為是成功了,成功之后就會合并成一個新的文件,對外生成一個可用的大文件。
HLS 協議
HLS 協議,全稱是 HTTP LIVE STREAMING 協議,是由蘋果推出的,可讀性很強。里面的每一個片都是一個 HTTP 請求,整個文本協議就是一個索引。
上圖是每一個視頻段的時長,這個是 8 秒是視頻的最大長度。直播的應用中會有一個 Sequence 從零開始遞增的,如果有一個新片,就會把舊片去掉,把新的加上去,并增加 Sequence。
任務隊列、均衡、流控
下面再介紹一下具體的功能實現,任務收到請求之后不是直接處理,而是異步處理的。先把請求分發到各個 Worker 的私有隊列,分發算法是用的 crc32,因為 crc32 足夠快、足夠輕量,基于一個 key 視頻流會有域名、App、stream,再加上 TS 的文件名稱。這樣分發可以很好地做一次負載均衡。基于這個任務隊列,可以處理大量的突發請求,如果突然有了數倍的請求,可以把這些消息發到 Redis 里,由 Redis 存儲這些請求。每個 Worker 會同步進行處理,把 TS 片上傳,上傳完之后再生成 M3U8 文件。我們現在對后端固定了連接數,一個 woker 一個鏈接,因為存儲集群的連接數量是有限的,現在采取一個簡單策略,后端能處理請求多快,就發送多快,處理完之后可以馬上發送下一個。因任務隊列是同步處理,是同步非阻塞的,不會發送超過后端的處理能力。
我們未來準備進行優化的方向就是把任務隊列分成多個優先級,高優先級的先處理,低優先級的降級處理。比如我們線上遇到的一些視頻流,它不太正常會大量的切小,比如正常視頻 10 秒一片,而它 10 毫秒就一片,這樣我們會把它的優先級降低,防止異常任務導致正常任務不能合理地處理。以后就是要實現可以動態調解鏈接數、請求速率和流量。如果后端的處理能力很強,可以動態增長一些鏈接數和請求速率,一旦遇到瓶頸后可以動態收縮。
任務分發比較簡單,主要就是上面的三行代碼,每一個 Worker 拿到一個任務后,把任務分發給相應的 Worker ,它的算法是拿到總 Worker 數然后基于 crc32 和 key ,得到正確的 Worker ID,把它加到任務隊列里。這樣的做法好處是每個任務分發是非單點的,每一個 Worker 都在做分發,把請求的任務發到任務隊列里,請求的元信息放入 Redis 里面,還有一個就是任務拉取消費的協程,拉取任務并執行。
失敗重試、降級、高可靠
如果數據量大會有很多失敗的任務,失敗任務需要放入失敗隊列,進行指數退避重試。重試成功后再進行后續處理,比如添加進點播 m3u8、分片 complete。分片 complete 是如果原來有 100 個任務會同時執行,但是現在有 3 個失敗了,我們可以判斷一下它是不是最后一個,如果是最后一個的分片就要調一下 complete,然后完成這個分片,完成整個事務。
同時我們做了一個 Redis 失敗時的方案,Redis 失敗后需要把 Redis 的數據降級存到本地,一部分存到 share dict,另一部分用 LRU cache,TS 對應 m3u8 的索引信息會用 share dict 做緩存。LRU 主要是存一些 m3u8 的 key,存儲哪些信息和流做了降級,Redis 恢復后會把這些信息同步到 Redis。因為存在于各個 Worker 里面數據量會比較大,有些任務會重復執行,我們下一步工作就想基于 share dict,加一個按照指定值來排序的功能,這樣就可以優先處理最近的任務,將歷史任務推后處理。
我們還有一些 M3U8 的列表數據存儲在 Redis,因為線上的第一版本是單實例的,存儲空間比較有限,但是現在對接的流量越來越多,單實例內存空間不足,于是我們做了支持 Redis 集群的工作,實現 Reids 高可用,突破內存限制。
還有一個比較兜底的策略:定期磁盤巡檢,重新處理失敗任務。事務可能是在任何的時點失敗的,但是只要我們能夠重做整個任務,業務流程就是完整的。
第一版的時候是全局的單一任務隊列,基于 resty lock 的鎖取保護這個隊列,每一個 woker 爭用鎖,獲取任務,鎖沖突比較嚴重,CPU 消耗也高,因為那個鎖是輪詢鎖,優化后我們去掉了一個鎖實現了無鎖,每一個 Worker一個任務隊列, 每個 Worker 基于 CRC_32 分發任務。
舊版一個 TS 更新一次 M3U8,一次生成一個哈希表,數量較多的情況下 CPU 開銷比較大。我們進行了優化,做了一些定時觸發的機制,進行定期更新,因為點播 M3U8 對時間是不敏感的,可以定期地更新,減少開銷。當然直播的 還是實時生產的,因為要保證直播的實時性。
直播方面如果異常切片太多,用戶也不能很好觀看,會進行主動丟片,主要是基于 Redis 鎖去實現;對于 Redis 內存消耗高的問題我們搭建了 Redis 集群。
我們開發了一個直播時移回看服務,根據用戶請求的時間去后臺下載相應的 M3U8 的數據進行裁剪拼接返回給用戶。這一塊的 M3U8 信息不是很大,非常適合用 MLCACHE 保存,它是一個開源的兩級緩存,Worker 一級的和共享內存一級,因為共享內存緩存有鎖沖突,MLCACHE 會把一些熱點數據緩存到 Worker 級別,這樣是無鎖的,使用后效果非常好,雖然文件不大,但是運行時間建連,網絡IO耗時很大,經過緩存之后可以大大提高處理效率,節省時間。時移的時候每一個用戶會也一個 Session 記錄上次返回的 M3U8 位置,因為直播流會有中斷,不是 24 小時都有流的,用戶遇到了一個斷洞,可以跳過看后面的視頻,時移不需要等待,并且用戶網絡短暫異常時不會跳片。
點擊觀看演講視頻和 PPT~
OpenResty 在直播場景中的應用
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40606.html
摘要:淺談秒殺系統架構設計后端掘金秒殺是電子商務網站常見的一種營銷手段。這兩個項目白話網站架構演進后端掘金這是白話系列的文章。 淺談秒殺系統架構設計 - 后端 - 掘金秒殺是電子商務網站常見的一種營銷手段。 不要整個系統宕機。 即使系統故障,也不要將錯誤數據展示出來。 盡量保持公平公正。 實現效果 秒殺開始前,搶購按鈕為活動未開始。 秒殺開始時,搶購按鈕可以點擊下單。 秒殺結束后,按鈕按鈕變...
摘要:在互聯網的第三個時代,也就是下一個互聯網十年里,云計算將成為這場大戰的制勝關鍵所在。就在前不久,亞馬遜旗下的云計算服務平臺宣布正式在中國商用。的殺入對于中國的云計算市場也是一大不可忽視的力量。 互聯網的第一個時代我們定義為PC互聯網,互聯網的第二個時代我們定義為移動互聯網,而互聯網的第三個時代我們則定義為萬物聯網。當前國內的互聯網正處于第二個時代向第三個時代過渡期,而云計算則是支撐起萬物聯...
摘要:服務教程在它提出十多年后的今天,已經成為最重要的應用技術之一。全方位提升網站打開速度前端后端新的技術如何在內完整打開網站會直接影響用戶的滿意度及留存率,在前端后端數據緩存加速等等方面都有諸多可以提升。 HTTPS 原理剖析與項目場景 最近手頭有兩個項目,XX 導航和 XX 產業平臺,都需要使用 HTTPS 協議,因此,這次對 HTTPS 協議做一次整理與分享。 使用緩存應該注意哪些問題...
閱讀 3490·2019-08-30 15:53
閱讀 3405·2019-08-29 16:54
閱讀 2189·2019-08-29 16:41
閱讀 2396·2019-08-23 16:10
閱讀 3376·2019-08-23 15:04
閱讀 1341·2019-08-23 13:58
閱讀 347·2019-08-23 11:40
閱讀 2451·2019-08-23 10:26