关于pipeline
最近要將系統改造成pipeline架構,所以研究了一下pipeline相關的理論,servlet filter, struts2 interceptor, spring mvc interceptor, webx pipeline和netty pipeline的一些源碼。一些總結:
結構:
Pipeline的類模型由Pipeline, Valve 和 Context 組成。 Pipeline代表一個執行流,Valve代表執行流中的一個節點,Context是執行時的上下文信息,它一般由兩部分組成: request/response + 當前流的執行狀態。
有的系統只能有一個Pipeline, 有的則允許配多個。 在struts2中,一種interceptor的組合,就代表了一個Pipeline;多種組合,意味著多個Pipeline.
用法:
有的pipeline流是在同一層次上,每個valve處理的request/response對象基本上是同質的。比如servlet filter和各種mvc框架,所處理的事情都是web層的,所處理的context對象就是http request或框架自定義的javabean.
有的pipeline流則是縱向的,從上層流到下層,或從下層流到上層,這時每個valve所處理的request/response對象一般是異構的。協議棧就是個典型的例子:下層valve處理字節流,上層Valve處理字符流。 不過,為了適應pipeline架構,這些異構的context對象必須有共同的基類,并且把這個基類作為各個valve的輸入參數。
從請求處理的角度來說, Pipeline可以代表整個執行流,也可以只用作請求被最終處理前的Interceptor. Webx, netty中的Pipeline會將最后一個Valve作為請求處理者(一般稱為Request Handler),而servlet filter和struts2 interceptor只作請求攔截、加工,真正的請求處理者則是servlet和action.
程序流:
一個完整的Pipeline執行流一般是個環路: Valve1 => Valve2 => Valve3 => Valve2 => Valve1. 從攔截的角度說,valve既是前置攔截(下一個valve執行前),又是后置拉截(下一個 valve執行后)。
為了達到前后雙攔截的目標,程序實現有兩種方法。 有一種方法是使用forEach方式分別執行每個攔截器的前置攔截方法,然后又以相反的順序分別執行每個攔截器的后置攔截方法。這種做法比較直觀,可以說直接映射了人類的思考方式。 Spring MVC Interceptor差不多就是這種做法。
另一種做法,也是主流的作法,則會把一個valve的執行嵌套在前一個valve的執行里面: 每個valve的執行中代碼中會有一句"nextValve.invoke()",然后在這句代碼的前后做一些攔截。這種方式有點費解,而且由于嵌套過多容易造成比較深的調用棧。 不過它有一個好處: 更方便地中斷執行流并處理異常(下詳)。
執行流須提供中斷機制和異常處理機制,比如一個鑒權filter在發現用戶未登錄時需要立即返回403并中斷流,當一個valve出現異常時這個異常需要被捕捉、處理。 如果Valve是嵌套執行的,這些機制會很方便實現: 鑒權filter發現用戶未登錄時,不調用nextValve.invoke()即可中斷pipeline; 至于異常處理,Struts2默認使用ExceptionMappingInterceptor作為Pipeline中的第1個valve, 它會把nextIntercetpor.invoke()放在自己的try/catch塊中。如果valve不是嵌套執行,而是由pipeline通過forEach編排執行的,那么這些非正常流的“扳道工”職責就必須由pipeline自己來承擔, 這可能會使pipeline不夠精簡;如果來了新的邏輯(比如異步執行),又得改pipeline,導致pipeline不太穩定。
設計模式:
狀態/無狀態, 單例/非單例. 如果不怕麻煩,可以每來一個請求,就生成一個Pipeline對象和一堆Valve對象,再把request和上下文信息用作這些對象的狀態;但是,用單例的風格更符合當代程序員的習慣,也更容易與spring結合。 那么,全單例并且都是無狀態? 不盡然。雖然Pipeline的結構本身是靜態的,一個pipeline結構可以作成一個單例;但Pipeline的執行流是有狀態的,比如當前執行到了哪個valve,是需要一個變量來維護的。 所以,可以做一個單例的對象Pipeline, 代表Pipeline的結構;另做一個對象PipelineContext,代表Pipeline當前的執行流;至于Valve,它相當于一個stateless service, 做成單例即可.
轉載于:https://www.cnblogs.com/wdmx/p/9895015.html
總結
以上是生活随笔為你收集整理的关于pipeline的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL------Hint
- 下一篇: 【sql】牛客网练习题 (共 61 题)