SEDA介紹與分析

SEDA(Staged Event-Driven Architecture)並不是很新的技術,但它總會在我閱讀的資料裏出現些許影子,所以就拿出一些時間看了一下與它相關的論文資料。SEDA的目標很遠大,它要構建支持大併發的互聯網系統,並克服多線程及事件驅動的服務器端模型的缺點。但SEDA來源於學術界,並且這個東西還是有些複雜了,所以至今工業級的應用不是很多。它的官網是http://www.eecs.harvard.edu/~mdw/proj/seda/,上面的一些論文還是很不錯的,值得拜讀。


對於服務端端處理模型,目前廣泛使用的有兩種:

1、多線程處理模型。這種模型由一個主線程和多個work線程構成,主線程負責接收請求,並將接收到的請求分發給合適的work線程處理,work線程處理完請求後直接將響應返回給客戶端。這種模型很簡單,也有着廣泛的應用,尤其是通常的後端模塊,處理邏輯在work線程裏是阻塞進行的。這個模型的缺點也很明顯,如果大量的work線程因爲某種原因被堵住(比如連接的DB響應太慢、從磁盤獲取文件數據等),將使得後續的請求得不到處理,而最經典的例子莫不過apache了。

2、事件驅動(Event-Driven)處理模型。這種模型克服了多線程模型的併發量缺點,對請求採用事件驅動方式處理,這裏的事件通常是IO事件,其底層的實現依賴於非阻塞IO和IO多路複用。事件驅動模型很適合於IO密集型的應用,這種應用對CPU消耗代價甚至要小於線程間的切換代價,比如各種proxy。而現在的proxy,基本都標配Epoll,使得能支持的併發請求數在萬級別。像lightty、nginx,是事件驅動模型的經典應用,請求的處理流程是由狀態機驅動的,每次狀態的切換經由一次事件觸發,這樣單線程就夠用了(當然,如果需要支持更高的處理能力,可以採用多進程的事件驅動模型)。事件驅動的缺點在於:1)單個處理階段不能阻塞太長,如果有這方面的問題,一般可採用專門的線程處理,處理完了再觸發事件讓主線程接着處理。2)整個事件驅動流程通常是固定的,在一個線程內由調度器完成,這使得它很難做的通用,使應用可以自定義流程。

基於上面提到的兩種模型的優缺點,SEDA被提出來,它的核心思路是:一個請求被分成多個stage進行處理,每個stage彼此間獨立,一個請求的多個stage可以串行化也可以並行化。stage內部使用Event-Driven,新到的請求放到event queue中,系統從thread pool中的選擇一個線程經由Event Handler處理,Event Handler處理完後將請求派發到下一個stage。下面的是假想的一個Web server的SEDA的處理流程:

wKiom1N9nk_DQiBcAAHLlTz_AXE396.jpg


對於SEDA中的每個stage,它由下面的三部分組成:

1)輸入的event queue。SEDA中的event queue的大小是有限制的。所以,如果event queue 達到閾值,新到的event可能會被拒絕或者轉發到特定的stage(比如錯誤處理stage)。

2)thread pool:這個線程池對應用是透明的,並且每個stage的線程池是彼此獨立的。針對請求量及特點,線程池可以動態的調整大小,不至於某個stage的線程池耗盡所有的資源。

3)event handler,event handler接收系統給予的event,做具體的邏輯處理後將event分發到其他stage。event handler通常需要應用開發者編寫。

wKioL1N9nm6Q0UJgAADh4qAYscU129.jpg

SEDA stage內部結構圖

針對各個stage運行時的狀態,SEDA引入resource controller來調整stage的資源分配和調度參數等。核心的兩個Controller是thread pool controller和batching controller。thread pool controller用來控制thread pool的運行時大小,比如當event queue很大時,就多分配些線程,反之則減少線程數。batching controller用來控制event handler同時處理的event的併發量(batching factor),當batching factor增大時,增加了吞吐量但event平均響應時間會變長,當batching factor變小時,情況相反。batching controller的控制效果使得batching factor的上下波動來控制吞吐量和響應時間。

wKiom1N9ntCSbo3oAAEKLxH1QKk535.jpg

SEDA controller結構圖

SEDA的一個實現框架是Sandstorm,開發者可以基於它開發應用。限於精力,沒有對它做實戰,但使用上來說,它還是很簡單的。可以想象的是,Sandstorm提供了一些編程接口做事件處理,並通過XML文件(Java的固有風格)來配置stage策略等。對於使用這樣分階段事件驅動框架來說,編程中需要注意stage間不要共享數據,併合理的劃分stage策略。

就應用來說,SEDA的多stage處理模型,能夠將應用組件化、模塊化,解耦了處理的不同階段,這可能很適合於如工作流等企業業務流程場景。但像通常簡單的後端模塊,對一個請求可能很難劃分出多個職責明確的stage,並且這種分stage策略也增加了處理流程的複雜度,性能上也會受到損失。所以,針對不同的應用特點,SEDA的實用性仍值得商榷。


本文轉載自:http://www.kafka0102.com/2010/02/34.html












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章