Red5 流處理架構設計解析
我們來看一下 Red5 通訊架構的類圖(MessagingFramework.png)。這些類只是根據我的個人分支(branches/dev_steveng),而且這些類並非架構的全部只是一部分,因為許多決定還是需要大家一起來做,但架構的整體已經設計完畢。主要分為五個部分:Provider, Consumer, Pipe, Event/Listener 和 IMessage。
為了使這個框架生效,我寫了幾個臨時介面卡封裝了我們遺留的流處理類,使之能夠 VOD,實時流及其錄製。類圖(adapter.png)顯示了這些介面卡是如何工作在 Red5 通訊架構中的。
** 消費者(Consumers) DownStreamAdapter 包裝好流之後,將 RTMP 包傳送給客戶端。它可以工作在兩種模式下,一種是拉模式另一種是推模式。在播放一個 VOD 時,它工作在拉模式,因為它主動地從管道(pipe)中獲取資訊所以我們稱之為主動消費者。但當它播放一個實時流的時候,它工作在推模式,我們稱之為被動消費者或者事件驅動消費者。 ** 供應者(Providers) FileStreamSourceAdapter 將 FileStreamSource 封裝起來,是一個拉模式的供給者又稱為被動供給者。這個很容易理解因為我們在 VOD 使用到了它。 LieStreamSourceAdapter 將流封裝起來,是一個推模式的供給者又稱為主動供給者。它在 RTMP 連線中獲取 RTMP 包並將其推送給管道(pipe)。 ** 訊息(Message) 在這裡我將原來的 Message 類簡單地封裝為 RTMPMessage 類。 ** VOD,實時和錄製(VOD, live and recording)現在我們來看一下這些介面卡是如何組織提供 VOD,實時和播放服務的。(注:我基於遺留 API 開發了這些介面卡,但它們也可以比較容易地為以後的類所用)
請參考圖 PlayVOD.png。在 VOD 中,當客戶端發起一個播放請求時,Stream 類將會使用 FileStreamSourceAdapter、DownStreamSourceAdapter 和 InMemoryPullPullPipe 建立一個管線(pipeline)。在播放時,RTMPMessage 由消費者 DownStreamSourceAdapter 獲取(MINA 對它進行觸發)。請參考圖 PublishLive.png 和 PlayLive.png。在這裡 StreamManager 充當了一個為連線供給者和消費者的中心管道記賬人(pipe)的角色。我畫的只是先有釋出然後才有播放的情形。釋出者和線上播放者由 InMemoryPushPushPipe 進行連線 -- LiveStreamSourceAdapter 充當了這一過程的主動的供給者而 DownStreamAdapter 則在推模式下進行連線。事實上,如果線上播放者先提出申請的話,它將會等待,直到釋出者提出申請。所以我們不再需要 TemporaryStream 和 TemporaryStreamSink 兩個類了。
請參考圖 Recording.png。除了 StreamManager 同時建立了一個 FileStreamSinkAdapter 之外這個時序圖幾乎跟線上釋出相同。理論上,當另一個播放者提出線上播放請求時,這個時序圖就會和 PlayLive.png 一樣了,但這樣火狐會崩潰的... :-(
> 通過上面的時序圖,我們有理由斷定本通訊架構可以使我們的程式碼更加模組化更加靈活。 * 管道連線事件模型(Pipe Connection Event Model) 提供者和消費者是怎樣進行排程的呢?比如說,當一個客戶端停止播放一個 VOD 並且關掉了 DownStreamAdapter(這個關閉由流觸發),FileStreamSourceAdapter 就不在需要了。我們需要通知前者是否也需要關掉 FileStreamSourceAdapter。所以當 DownStreamAdapter 關掉並且斷開與管道(pipe)的連線時,我們應該想到一個方法去通知 FileStreamSourceAdapter 或更多類似者通知想要關閉的供應者。很容易理解消費者指向供應者,就是說,DownStreamAdapter 擁有一個 FileStreamSourceAdapter 成員並且當自己關閉時通知檔案源,但這會造成耦合。如果供應者和消費者之間有過濾器的話事情會變得很糟,就是說,一個 SpeedControlFilter 定位於 DownStreamAdapter 和 FileStreamAdapter 之間。 為了解決這一問題,我們可以引進一個事件模型。無論什麼時候一個供應者或者消費者連線到管道(pipe)時,所有注入到管道(pipe)的監聽者會被通知到,如果供應者和消費者也是監聽者他們會被自動通知。這就是為什麼我們看到在介面卡的類圖上所有的介面卡都實現了 IPipeConnectionListener 的原因。通過事件模型機制,資源釋放就很容易實現,而且還鬆耦合。請參考圖 Dispose.png,時序圖表明當 DownStreamAdapter 消亡時,FileStreamSourceAdapter 也會相應地消亡。FileStreamSinkAdapter 同理。
在這裡,DownStreamAdapter 關閉並且登出(斷開)了和管道(pipe)的連線。另一端的供應者(FileStreamSourceAdapter)收到通知也相應地關閉。現在讓我們想像一下當有一個 SpeedControllerFilter 在二者之間時的情形。過濾器將會被通知進而自行關閉。然後 FileStreamSourceAdapter 也會被通知到。所以事件從 DownStreamAdapter 向下通過管道(pipe)傳遞給了 FileStreamSourceAdapter。 * 日程列表(TODO list) ** 設計訊息模型(Design the message model) 首先,我們需要確定下來所有通訊類的體系。我已經將它設計成包含頭和體的模型了,就像傳統的 JMS 所坐的那樣。我不確定這樣是否可以。我們需要蒐集所有的 Red5 用到的通訊型別並且把它們進行建模。到目前為止我認為 RTMPMessage 和 RawByteMessage 是我們需要的。 ** 管線的生命週期管理(Lifecycle management of pipeline) 通訊框架並沒有提及管線(pipeline 由管道(pipe)連線起來的供應者、消費者和過濾器)是如何建立、管理和銷燬的,我們應該考慮一個靈活的方案去實現這些。比如說,管線(pipeline)可以通過一個 xml 檔案進行配置(就像 cocoon 所做的那樣)。管線(pipeline)可以通過一個良好設計的 API 由應用程式開發人員在執行時進行建立,這樣應用程式開發人員可以決定管線(pipeline)是如何進行建立的:它是否需要一個 SpeedControlFilter,或者它將支援多點傳送,或者它將需要一個基於客戶端的安全管理(SecurityFilter)。應用程式開發人員也可以在自己的程式執行的時候改變管線(pipeline),就是說,實時地替換或者移除掉一個過濾器。 ** 管理管線的 API(API that manages the pipeline) 上面已經提到過了。 ** 流程式碼的重構(Refactor the streaming code) 使用介面卡只是權宜之計。我們需要將遺留的流處理程式碼進行重構讓它變的基於元件,這樣子這些元件才可以自行包含、自行文件和可以進行單元測試。這樣我們才可以把它們連線起來執行在我們的系統中。==========================================================================================================原文連結:http://osflash.org/pipermail/red5devs_osflash.org/2006-April/000703.html。