模式定義
管道過濾器模式將執行復雜處理的任務分解為可重復使用的一系列離散元素,這種模式可以提高性能,可擴展性和可重用性,允許執行部署和縮放獨立處理的任務元素。
特定場景
整個應用的處理可以被分解成一系列離散的,獨立的步驟的情況下,可以考慮使用管道過濾器模式。
當應用處理的不同的步驟,有不同的擴展性需求的情況下,可以考慮實現管道過濾器模式。
如果需要較強的靈活性的時候,可以考慮使用管道過濾器模式。管道過濾器模式令應用可以靈活的配置不同的執行步驟和執行序列,而且應用還可以按需來增加或者減少對應的處理單元。
當需要最大化服務器利用率的時候,可以選擇管道過濾器模式。
如果解決方案需要保證的可靠,需要盡量降低每一個單獨的處理單元中執行的失敗的可能性的時候,可以考慮使用管道過濾器模式。
管道過濾器模式將執行復雜處理的任務分解為可重復使用的一系列離散元素,這種模式可以提高性能,可擴展性和可重用性,允許執行部署和縮放獨立處理的任務元素。
問題
一個應用程序可能根據其處理的不同的信息需要執行各種復雜的任務。一個簡單的,但不靈活的方法就是可以將應用的處理作為一個單獨的模塊。但是,如果部分相同的處理需要在應用程序的其他地方,這種方法可能會減少代碼重構,重用,優化的機會。
很多獨立模塊執行的一些任務在功能上非常相似,但是因為這些模塊是分開設計的,實現任務的代碼都是緊密耦合在一個模塊中,其中的重復部分無法得到重用來提高擴展性和重用性。
然而,每個模塊執行的處理任務,或每個任務的部署要求,可能都會隨着業務需求的修改而改變。有些任務可能是計算密集型的,可能會受益於運行在強大的硬件,而其他任務可能不需要這樣昂貴的資源。此外,在未來可能需要執行一些額外的處理,或命令執行的任務可能會改變。所以需要一個技能解決這些問題,同時也能增加代碼重用的解決方案。
解決方案
將每個數據流所需的處理分解成一組離散的組件(或過濾器),然后由每個組件來執行一個任務是一種不錯的解決方案。通過標准化每個組件接收和發出的數據的格式,這些組件(過濾器)可以組合成一個管道。這種解決方案有助於避免重復代碼,並且在需求發生變化的時候,可以很容易地刪除,替換或集成額外的組件來實現功能。
處理單個請求的時間取決於管道中最慢的過濾器的速度。尤其在大量請求發送到組件的時候,某個或者某些組件就可能成為系統的性能瓶頸。管道結構的一個主要優點就在於,它為運行緩慢的過濾器提供了使用並行實例的機會,這樣使系統能夠均衡負載,以提高吞吐量。
組成管道的過濾器完全可以運行在不同的機器上,並且它們可以利用許多雲環境提供的彈性能夠來實現獨立擴展。一個計算密集型的過濾器可以運行在高性能硬件上,而其他要求較低的過濾器可以運行在稍差的硬件上。過濾器甚至不必在相同的數據中心或不在同一個地點,管道解決方案允許管道中的每個元素可以在接近其所需資源的環境中運行。
如果一個過濾器的輸入和輸出被結構化為一個流,它就有可能對多個過濾器進行並行處理。管道中的第一個過濾器可以開始它的工作,並開始分發它的處理結果,這是直接傳遞到下一個過濾器的序列之前,第一個過濾器已完成其工作。
另一個好處是管道過濾器模式可以提供很好的跳轉。如果過濾器失敗或正在運行的機器不再可用,則管道可以重新安排過濾器正在執行的工作,並將此工作直接指向組件的另一實例。一個過濾器的故障並不會導致整個管道的故障。
使用管道和過濾器模式與事務補償模式相結合,可以提供一種替代的方法來實現分布式事務。分布式事務可以分解成獨立的有償任務,每一個都可以通過使用一個過濾器,還實現了事務補償模式。管道中的過濾器可以作為獨立的托管任務來執行,這些任務還可以在物理位置上接近他們所維護的數據,以降低網絡代價。
實例
Servlet Filter
凡是開發過J2EE的web application的人員都知道,經常需要處理以下幾種情況:
- 訪問特定資源(Web 頁、JSP 頁、servlet)時的身份認證
- 應用程序級的訪問資源的審核和記錄
- 應用程序范圍內對資源的加密訪問,它建立在定制的加密方案基礎上
- 對被訪問資源的及時轉換, 包括從 servlet 和 JSP 的動態輸出
在servlet2.3之前這些功能處理是很難實現的,但是Java Servlet 2.3 規范新增了不少激動人心的功能,其中之一便是過濾器(Filter),其實這就是我們所說的管道和過濾器體系架構在J2EE中的應用實踐. 通過使用該模式使得Web Application開發者能夠在請求到達Web資源之前截取請求,在處理請求之后修改應答。
一個執行過濾器的Java 類必須實現javax.servlet.Filter 接口。這一接口含有三個方法:
- init(FilterConfig):這是容器所調用的初始化方法。它保證了在第一次 doFilter() 調用前由容器調用。它能獲取在 web.xml 文件中指定的filter初始化參數。
- doFilter(ServletRequest, ServletResponse, FilterChain):這是一個完成過濾行為的方法。它同樣是上一個過濾器調用的方法。引入的 FilterChain 對象提供了后續過濾器所要調用的信息。
- destroy():容器在銷毀過濾器實例前,doFilter()中的所有活動都被該實例終止后,調用該方法。