【譯】SEDA: An Architecture for Well-Conditioned, Scalable Internet Services

                              Matt Welsh, David Culler, and Eric Brewer
                               Computer Science Division
      University of California, Berkeley {mdw,culler,brewer}@cs.berkeley.edu

概述

 我們爲高度併發的Internet服務提出了一種新設計,我們將其稱爲分階段事件驅動架構(SEDA)。SEDA旨在支持大規模併發需求並簡化良好服務的構建。在SEDA中,應用程序由通過顯式隊列連接的階段事件驅動網絡組成。這種架構使服務具有良好的負載,在需求超過服務容量時防止資源過度使用。儘管負載波動很大,但SEDA利用一組動態資源控制器將各階段保持在其運行狀態。我們描述了幾種用於自動調整和負載調節的控制機制,包括線程池大小調整,事件批處理和自適應負載消減。我們介紹了SEDA設計以及基於該架構的互聯網服務平臺的實現。我們通過兩個應用程序評估SEDA的使用:用於Gnutella(無結構的P2P網絡代表軟件)對等文件共享網絡的高性能HTTP服務器和數據包路由器。這些結果表明,SEDA應用程序表現出比傳統服務設計更高的性能,並且對於負載的巨大變化具有穩健性。

1引言

      互聯網呈現出前所未有的計算機系統問題:要求支持數百萬用戶的訪問,服務必須是相應的、穩健的、始終可用的。Internet站點每天的併發會話數和點擊次數轉化爲更多的I/O和網絡請求,對底層資源提出了巨大的要求。雅虎每天收到超過12億的頁面瀏覽量,AOL的網絡緩存每天提供超過100億次點擊。此外,互聯網服務在服務負載方面經歷巨大變化,突發與服務具有最大價值的時間一致。詳細記錄的“Slashdot效應”表明,當網站變得流行時,需求增長超過100倍並不罕見。隨着對互聯網服務的需求的增長,必須使用新的系統設計技術來管理這種負載。
      這種系統挑戰被三種趨勢放大,這些趨勢增加了服務的普遍性。首先,服務本身變得越來越複雜,靜態內容被涉及大量計算和I/O的動態內容所取代。其次,服務邏輯趨於快速變化,這增加了工程和部署的複雜性。第三,服務越來越多地託管在通用設施上,而不是在爲特定服務精心設計的平臺上。隨着這些趨勢的繼續,我們設想將創建一系列豐富的新穎服務並將其推入基礎設施,在這些基礎設施中,它們可能會成功擴展到數百萬用戶。一些研究正在解決服務的高級方面,包括命名,查找,組合和版本控制。我們將重點放在問題的性能方面:在負載變化很大的情況下,在廣泛的服務上實現強大的性能,同時保持其易用性。複製是服務可伸縮性的關鍵方面。給定一個可以維持一定性能水平的服務實例,必須複製它以維持負載的多倍增加,可擴展的集羣現在被廣泛用於在服務站點內獲得複製,並且廣泛的複製越來越多地用於特定服務,例如內容分發網絡。但是,因爲峯值負載可能比平均值大幾個數量級,所以它不實用。複製大多數服務以處理最大的潛在需求。 因此,我們預計每個節點所承受的負載會出現大幅峯值。我們的目標是開發一個通用框架,用於創建高度併發且運行良好的服務實例,以便優雅地處理負載。
      遺憾的是,傳統的操作系統設計和廣泛推廣的併發模型並不能提供這種優雅的負載管理。商品操作系統專注於通過爲每個進程提供獨有的CPU,內存,磁盤和網絡的虛擬機的抽象來提供最大的透明度。 這個目標與互聯網服務的需求有些不一致,互聯網服務需要大量的併發性和對資源使用的廣泛控制。進程和線程是良好支持的併發編程模型,但在上下文切換時間和內存佔用方面往往需要很高的開銷,這限制了併發性。 透明的資源虛擬化阻止了應用程序做出明智的決策,這對於管理過多的負載至關重要。大多說工作都側重於特定服務的性能和穩健性。然而,隨着服務變得越來越動態和靈活,這種工程負擔變得過度。很少有工具可以幫助開發高度併發,運行良好的服務; 我們的目標是通過提供幫助軟件開發人員獲取這些屬性的通用機制來降低這種複雜性。
      我們爲高度併發的服務器應用程序提出了一個新的設計框架,我們將其稱爲分階段事件驅動架構(SEDA)。SEDA結合了線程和基於事件的編程模型的各個方面來管理Internet服務的併發性,I/O,調度和資源管理需求。在SEDA中,應用程序被構建爲階段網絡,每個階段都具有關聯的傳入事件隊列。每個階段可以通過單獨調節負載閾值或過濾其事件隊列來構建一個健壯的模塊。此外,使事件隊列顯式化允許應用程序進行合適的調度和資源管理決策,例如重新排序,過濾或聚合請求。SEDA利用動態資源限制來控制應用程序組件的資源分配和調度,使系統能夠適應過載狀態。
      本文描述了基於SEDA的Internet服務平臺的設計,體系結構和實現。該平臺提供高效,可擴展的I/O接口以及多種資源控制機制,包括線程池大小調整和動態事件調度。我們通過兩個應用程序評估框架 - 一個高性能HTTP服務器和一個用於Gnutella對等文件共享網絡的數據包路由器。我們爲這些應用提供了性能和可擴展性結果,證明了SEDA在負載的巨大變化上實現了穩健性,並且優於其他服務設計。我們基於Java的SEDA HTTP服務器優於基於C實現的兩個流行的Web服務器,如第5.1節所述。我們認爲使用SEDA,高度併發的應用程序更容易構建,更高效,更強大的負載。通過正確的接口,應用程序設計人員可以專注於特定於應用程序的邏輯,而不是併發和資源管理的細節。

2背景和相關工作

      SEDA彙集了兩個重要的研究領域:使用基於線程的併發模型來簡化編程,使用基於事件的模型來實現大規模的併發。本節通過概述主導SEDA設計的步驟中的關鍵貢獻和問題來闡明開發這種方法的譜系。
      直觀地說,如果服務的行爲類似於簡單的管道,那麼服務就是運行良好的,管道的深度由通過網絡的路徑和服務本身內的處理階段決定。隨着提供的負載增加,交付的吞吐量按比例增加,直到管道充滿並且吞吐量飽和; 額外的負載不應該降低吞吐量。類似地,服務所呈現的響應時間在輕負載時大致恆定,因爲它由管道的深度支配。當負載接近飽和時,排隊延遲占主導地位。在許多服務典型的閉環場景中,每個客戶端在提交下一個請求之前等待響應,響應時間應隨客戶端數量線性增加。
      良好的服務的關鍵屬性是優雅降級:當提供的負載超過容量時,服務保持高吞吐量,線性響應時間損失同等地影響所有客戶端,或者至少根據某些特定於服務的策略可預測影響。請注意,這不是典型的Web體驗; 相反,隨着負載的增加,吞吐量會降低,響應時間也會大幅增加,從而產生服務崩潰的印象。

2.1 基於線程的併發

      服務器應用程序最常用的設計是thread-per-request線程模型,如RPC包,Java遠程方法調用和DCOM中所體現的。 當前的語言和編程環境很好地支持這個模型。 在此模型中,如圖1所示,每個接受的請求都使用一個線程來處理它,同步操作受保護的共享資源。操作系統通過在線程之間透明切換來交叉計算和I/O.
這裏寫圖片描述
圖1:線程服務器設計:將每個傳入請求分派到一個單獨的線程,該線程處理請求並將結果返回給客戶端。邊表示分支之間的控制流。請注意,此處未顯示其他I/O操作(如磁盤訪問),但會將其合併到每個線程的請求處理中。
      儘管編程相對容易,但與線程相關的開銷(包括緩存和TLB未命中,調度開銷和鎖爭用)當線程數量變大時,會導致嚴重的性能下降。作爲一個具體示例,圖2顯示了隨着線程數量的增加,簡單線程服務器的性能。儘管有效的線程限制對於通用分時來說會很大,但它不足以滿足Internet服務的巨大併發要求。
這裏寫圖片描述
圖2:線程服務器吞吐量降低
縱座標表示吞吐量(每秒任務數) 橫座標表示線程數
紅線代表吞吐量 藍線代表實際延遲走勢 紫線代表理想狀態下線性延遲走勢
此基準測試用於測量一個簡單的線程服務器,該服務器爲管道中的每個任務創建單個線收到任務後,每個線程從磁盤文件執行8 KB讀取; 所有線程都從同一個文件讀取,因此數據總是在緩衝區緩存中。線程在服務器中預先分配,以消除測量中的線程啓動開銷,並在內部生成任務以消除網絡效應。該服務器採用C語言實現,運行在Linux 2.2.14下的4路500 MHz Pentium III和2 GB內存上。 隨着併發任務數量的增加,吞吐量會增加,直到線程數量增大,之後吞吐量會大幅下降。 隨着任務隊列長度的增加,響應時間變得無限制; 爲了比較,我們已經顯示了理想的線性響應時間曲線(注意x軸上的對數刻度)。
      線程和進程主要用於支持多道程序設計,現有的OS力求以對應用程序透明的方式虛擬化硬件資源。應用程序很少有機會參與系統範圍的資源管理決策,或者給出資源可用性的指示,以使其行爲適應不斷變化的條件。虛擬化從根本上隱藏了資源有限和共享的事實。
      許多系統試圖通過嚮應用程序公開更多控制來解決這個問題。調度程序激活[5],應用程序特定處理程序[59]和操作系統(如SPIN [11],Exokernel [28]和Nemesis [34])都試圖通過爲應用程序提供特化內核做出的決策的能力來增強有限的操作系統接口。然而,這些系統的設計仍然基於多道程序設計,因爲重點仍然放在安全和有效的資源虛擬化上,而不是優雅的管理和高併發性。

2.2 有界線程池

      爲了避免過度使用線程,許多系統採用粗略形式的負載調節,用於綁定與服務關聯的線程池的大小。 當服務器中的請求數超過某個固定限制時,不接受其他連接。 Web服務器(如Apache [6],IIS [38]和Netscape Enterprise Server [42])以及應用程序服務器(如BEA Weblogic [10]和IBM WebSphere [25])使用此方法。 通過限制併發線程的數量,服務器可以避免吞吐量降低,並且整體性能比無約束的每任務線程模型更強大。但是,這種方法會給客戶端帶來很多不公平:當所有服務器線程忙或被阻塞時,客戶端請求在網絡中排隊等待服務。正如我們將在5.1節中所示,這可能導致客戶端經歷任意大的等待時間。
      當每個請求由單個線程處理時,很難識別內部性能瓶頸以執行調整和負載調節。 考慮一個簡單的線程Web服務器,其中一些請求處理起來成本低廉(例如,緩存的靜態頁面)而其他請求則很昂貴(例如,不在緩存中的大頁面)。 對於許多併發請求,昂貴的請求可能是性能瓶頸的來源,因此需要執行減載。 但是,服務器無法檢查內部請求流以實現此類策略; 它所知道的是線程池已經飽和,並且一定是在不知道瓶頸來源的情況下隨意拒絕工作。
      資源容器[7]和來自Scout操作系統[41,49]的路徑概念是兩種可用於限制服務器中任務的資源使用的技術。這些機制將垂直資源管理應用於一組軟件模塊,允許整個數據流通過系統的資源作爲一個單元進行管理。 在上述瓶頸的情況下,限制給定請求的資源使用,將避免由於高速緩存未命中而導致的降級,但允許高速緩存命中繼續進行。

2.3事件驅動的併發

      線程的可伸縮性限制導致許多開發人員幾乎完全避開它們,並採用事件驅動的方法來管理併發。在這種方法中,如圖3所示,服務器由少量線程(通常每個CPU一個)組成,它們不斷循環,處理隊列中不同類型的事件。事件可以由操作系統生成,也可以由應用程序在內部生成,通常對應於網絡和磁盤I/O就緒和完成通知,定時器或其他特定於應用程序的事件。事件驅動方法將每個任務的處理實現爲有限狀態機,其中FSM(finite state machine)中的狀態之間的轉換由事件觸發。通過這種方式,服務器爲每個任務維護自己的連續狀態,而不是依賴於線程上下文。
這裏寫圖片描述
圖3:事件驅動的服務器設計:此圖顯示了通過事件驅動的服務器的事件流。 主線程處理來自網絡,磁盤和其他來源的傳入事件,並使用它們來驅動許多有限狀態機的執行。 每個FSM代表通過系統的單個請求或執行流程。 此設計的複雜性的關鍵來源是事件調度程序,它必須控制每個FSM的執行。
      事件驅動設計被許多系統使用,包括Flash [44],thttpd [4],Zeus [63]和JAWS [24] Web服務器以及Harvest [12] Web緩存。在Flash中,服務器的每個組件都響應特定類型的事件,例如套接字連接或文件系統訪問。主服務器進程負責不斷地將事件分派給每個組件,這些組件實現爲庫調用。因爲某些I/O操作(在這種情況下,文件系統訪問)沒有異步接口,所以主服務器進程通過IPC將它們分派給輔助進程來處理這些事件。幫助程序處理髮出(阻塞)I/O請求並在完成時將事件返回到主進程。Harvest的結構非常相似:它是單線程和事件驅動的,但FTP協議除外,它由一個單獨的進程實現。(Harvest:google搜索到是一款面向自由職業者和小型企業的時間跟蹤和在線發票應用程序。)
      線程和事件驅動的併發模型之間的權衡已經在JAWS Web服務器中進行了廣泛的研究[23,24]。JAWS(一個高性能的web服務器架構,jaws設計論文)爲Web服務器構建提供了一個框架,允許自定義併發模型,協議處理代碼,緩存文件系統和其他組件。與SEDA一樣,JAWS強調服務設計中適應性的重要性,通過促進服務框架中的靜態和動態適應性。據我們所知,JAWS僅在輕載(少於50個併發客戶端)下進行了評估,並未解決在高負荷下使用適應性進行調節的問題。
      事件驅動系統往往對負載具有穩定性,隨着提供的負載增加超出飽和度,吞吐量幾乎沒有降低。 圖4顯示了使用圖2中的服務的事件驅動版本實現的吞吐量。隨着任務數量的增加,服務器吞吐量會增加,直到管道填滿並且瓶頸(在這種情況下爲CPU)變得飽和。 如果管道中的任務數量進一步增加,則多餘的任務將被吸收在服務器的事件隊列中。 吞吐量在很大的負載範圍內保持不變,每個任務的延遲線性增加。
這裏寫圖片描述
圖4:事件驅動的服務器吞吐量:該基準測試用於測量圖2中服務器的事件驅動版本。在這種情況下,服務器使用單個線程來處理任務,其中每個任務從單個磁盤文件讀取8 KB。儘管此處使用的操作系統(Linux 2.2.14)提供的文件系統接口是阻塞的,但由於磁盤數據始終位於緩存中,因此此基準測試可估算非阻塞磁盤I/O層的最佳性能。如圖所示,當負載增加到非常大量的任務時,吞吐量保持不變(注意圖2中水平軸刻度的變化),響應時間是線性的(注意x軸上的對數刻度)。
      此模型的一個重要限制是它假定事件處理線程不會阻塞,因此必須使用非阻塞I/O機制。雖然許多先前的工作已經研究了可伸縮的I/O原語[8,9,33,46,48],但由於中斷,頁面錯誤或垃圾收集,事件處理線程會造成阻塞而不管所使用的I/O機制如何。
      事件驅動的設計爲應用程序開發人員帶來了許多額外的挑戰。 事件的調度和排序可能是最重要的問題:應用程序負責決定何時處理每個傳入事件以及處理多個流的FSM的順序。 爲了平衡公平性和低響應時間,應用程序必須仔細地複用多個FSM的執行。事件調度算法的選擇通常是針對特定應用而定製的,並且新功能的引入可能需要重新設計算法。此外,模塊化很難實現,因爲必須信任實現每個狀態的代碼,以阻止或消耗大量可能使事件處理線程停滯的資源。

2.4結構化事件隊列

      已經提出了關於標準事件驅動設計的若干變體來解決上述問題。 這些設計的一個共同方面是使用一組事件隊列構建事件驅動的應用程序,以提高代碼模塊性並簡化應用程序設計。
      Click模塊化分組路由器(Click路由器論文)[40]就是這樣一個例子。在Click中,數據包處理階段由具有自己的私有狀態的單獨代碼模塊實現。Click經過優化,可通過路由器改善每個數據包的延遲,允許單個線程直接通過多個數據包處理階段進行調用。 此設計針對特定應用程序(路由),單個線程爲所有事件隊列提供服務。Click假設模塊具有有限的處理時間,從而導致相對靜態的資源管理策略。Qie(Qie路由器論文)等。[47]還描述了在基於軟件的路由器中調度和負載調節的技術; 與SEDA一樣,他們的設計利用控制器根據負載動態調整運行時參數。
      Gribble的分佈式數據結構(DDS)[20]層也使用了結構化的事件處理框架。在DDS中,存儲服務器通過使用固定大小的線程池來模擬異步網絡和磁盤I/O接口,並且使用顯式事件隊列或隱式上行調用來組成軟件組件。Work Crews [56]和TSS/360隊列掃描程序[35]是利用結構化事件隊列和有限數量的線程來管理併發性的系統的其他示例。在這些系統的每一箇中,事件隊列的使用解耦了兩個組件的執行,這提高了模塊性和穩定性。
      StagedServer [31]是另一個利用顯式事件隊列進行通信的系統。 在這種情況下,目標是通過仔細調度每個模塊中的線程和事件來最大化處理器緩存局部性。 通過聚合隊列中多個類似事件的執行,增強了局部性,從而提高了性能。(譯者注:線程跳轉越少,局部性就會更好)
      Lauer和Needham的經典論文[32]討論了通過消息進行通信的過程的優點,並將這種方法與“procedures”的方法進行了對比,這與上述線程模型密切相關。 SEDA可以看作是那裏討論的面向消息的模型的一個實例。 作者聲稱基於消息和基於過程的模型是彼此的雙重性,並且在一個模型中實現的任何程序都可以在另一個模型中有效地實現。 雖然我們同意這種基本情緒,但這一論點忽略了構建可擴展通用多線程的複雜性,以及在沒有顯示請求隊列的情況下在基於線程的模型中調整負載的固有困難。

3分階段事件驅動架構

      在本節中,我們提出了一種新的軟件架構,即分階段事件驅動架構(SEDA),旨在實現Internet服務的高併發性,負載調節和易於設計。SEDA將應用程序分解爲由事件隊列分隔的階段網絡,並引入動態資源控制器的概念,以允許應用程序動態調整以適應不斷變化的負載。SEDA服務設計方法概述如圖5所示。
這裏寫圖片描述
圖5:分階段事件驅動(SEDA)HTTP服務器:這是基於SEDA的Web服務器的結構表示,在5.1節中有詳細描述。 應用程序由一組由隊列分隔的階段組成。邊緣代表階段之間的事件流。每個階段都可以獨立管理,階段可以按順序或並行運行,也可以兩者結合使用。事件隊列的使用允許每個階段單獨地加載條件,例如,通過對其事件隊列進行閾值處理。爲簡單起見,從該圖中省略了一些事件路徑和階段。

3.1目標

SEDA的主要目標如下:
支持大規模併發:爲避免因爲線程導致性能下降,SEDA儘可能使用事件驅動的執行。 這還要求系統提供高效且可擴展的I/O原語。
簡化良好條件服務的構建:爲了降低構建Internet服務的複雜性,SEDA保護應用程序開發者免受許多調度和資源管理的細節。該設計還支持這些應用程序的模塊化構造,併爲調試和性能分析提供支持。
啓用自我檢查:應用程序應該能夠分析請求流,以使行爲適應不斷變化的負載條件。 例如,系統應該能夠確定優先級並過濾請求,以支持在高負載下降級服務。
支持自我調優資源管理:系統應該動態調整其資源管理參數以滿足性能目標,而不是強制要求應用程序資源需求和客戶端負載特性的先驗知識。例如,分配給階段的線程數可以根據感知的併發需求自動確定,而不是由程序員或管理員硬編碼。

3.2作爲健壯構建塊的階段

      SEDA內的基本處理單位是stage。stage是一個獨立的應用程序組件,由事件處理程序,傳入事件隊列和線程池組成,如圖6所示。每個階段由影響調度和線程分配的控制器管理,如下所述。階段線程通過從傳入事件隊列中拉出一批事件並調用應用程序提供的事件處理程序來進行操作。事件處理程序處理每批事件,並通過將它們排入其他階段的事件隊列來調度零個或多個事件。
這裏寫圖片描述
圖6:SEDA階段:階段由傳入事件隊列,線程池和應用程序提供的事件處理程序組成。 階段的操作由控制器管理,控制器動態調整資源分配和調度。
      線程是SEDA中的基本併發機制,但它們的使用僅限於每個階段的少量線程,而不是系統中每個任務一個線程。此外,動態控制的使用(參見3.4節)可以根據需求自動調整分配給每個階段的線程數。此設計允許階段按順序或並行運行,或兩者的組合,取決於線程系統和調度程序的特性 在本文中,我們假設在SMP環境中的操作系統支持搶佔式線程,儘管這種選擇不是SEDA設計的基礎。例如,可以設計一個線程系統,它認識到應用程序的分階段結構並相應地調度線程。 我們在3.4節回到這個問題。
      每個階段的核心邏輯由事件處理程序提供,其輸入是一批多個事件。 事件處理程序無法直接控制隊列操作或線程。通過將核心應用程序邏輯與線程管理和調度分離,該階段能夠控制事件處理程序的執行以實現各種資源管理策略。例如,傳遞給事件處理程序的事件的數量和順序可以由運行時環境在外部控制。但是,應用程序還可以通過過濾或重新排序傳遞給它的事件批來實現自己的調度策略。

3.3作爲階段網絡的應用

      SEDA應用程序構建爲階段網絡,由事件隊列連接。事件處理程序可以通過首先獲取該階段的傳入事件隊列的句柄(通過系統提供的查找例程),然後在該隊列上調用入隊操作,將事件排入另一個階段。
SEDA中事件隊列的一個重要方面是它們可能是有限的:也就是說,如果隊列希望拒絕新條目(例如,因爲它已達到閾值),則入隊操作可能會失敗。當排隊操作失敗時,應用程序可以使用背壓(通過阻塞整個隊列)或減載(通過丟棄事件)。或者,應用程序可能希望採取某些特定於服務的操作,例如向用戶發送錯誤,或執行替代功能,例如提供降級服務。
      圖5說明了基於SEDA的應用程序的結構,在本例中是5.1節中描述的Haboob Web服務器。該應用程序包含許多特定於應用程序的階段,用於處理HTTP請求,實現頁面緩存等,以及運行時提供的幾個通用階段,以支持異步I/O. 這些接口在第4節中進一步描述。
      階段之間引入隊列通過採用顯式控制邊界來解耦其執行。此模型將線程的執行約束到給定階段,因爲線程可能只通過將事件排入隊列來跨控制邊界傳遞數據。一個基本問題是兩個代碼模塊是應該通過隊列進行通信,還是直接通過子程序調用進行通信。在兩個模塊之間引入隊列可提供隔離,模塊化和獨立負載管理,但可能會增加延遲。例如,第三方代碼模塊可以在其自己的階段中隔離,允許其他階段通過其事件隊列與之通信,而不是直接調用它。
      SEDA設計有助於服務的調試和性能分析,這對於複雜的多線程服務器來說一直是一個挑戰。 將應用程序代碼分解爲階段和顯式事件傳遞機制有助於檢查; 例如,調試工具可以跟蹤通過系統的事件流,並可視化階段之間的交互。 由於各階段通過事件調度協議而不是傳統API進行交互,因此可以直接在組件之間插入代理階段以進行調試和性能分析。 使用這種機制,我們的SEDA原型能夠生成描繪應用程序階段及其關係的圖表。 原型還可以生成事件隊列長度,內存使用和其他系統屬性的時間視圖,這些屬性對於理解性能很有價值。

3.4動態資源控制器

      實現易於服務工程的關鍵目標是保護程序員免受性能調優的複雜性。 爲了使每個階段保持在其運行狀態內,SEDA利用一組資源控制器,根據觀察到的性能和需求自動調整階段的資源使用。 抽象地,控制器觀察階段的運行時特性並調整分配和調度參數以滿足性能目標。 控制器既可以完全掌握關於特定階段的本地知識,也可以基於全局狀態協同工作。
      我們在SEDA中實現了幾個資源控制器,其中兩個如圖7所示。第一個是線程池控制器,它調整每個階段內執行的線程數。 目標是避免分配太多線程,但仍有足夠的線程來滿足階段的併發需求。 控制器定期對輸入隊列進行採樣,並在隊列長度超過某個閾值時添加一個線程,最多爲每個階段的最大線程數。 當線程空閒一段指定的時間後,線程將從一個階段中刪除。 圖8顯示了在5.1節中描述的Web服務器中運行的線程池控制器的影響; 控制器操作將在4.2節中詳細討論。
這裏寫圖片描述
圖7:SEDA資源控制器:每個階段都有一個關聯的控制器,可以調整其資源分配和行爲,以使應用程序保持在其運行狀態。 線程池控制器調整在階段內執行的線程數,批處理控制器調整事件處理程序的每次迭代處理的事件數。
      第二個是批處理控制器,它調整每個階段內事件處理程序調用處理的事件數(批處理因子)。 已經觀察到[31]一次處理許多事件會增加吞吐量,因爲可以執行緩存局部性和任務聚合。 但是,較大的批處理因子也會增加響應時間。 控制器試圖通過搜索維持高吞吐量的最小批處理因子來權衡這些影響。 它通過觀察來自一個階段的事件的輸出速率(通過維持許多樣本的移動平均值)來操作,並降低批處理因子直到吞吐量開始降低。 如果吞吐量略有下降,則批處理因子會少量增加。 控制器通過將批處理因子重置爲其最大值來響應負載的突然下降。 圖9顯示了工作中的批處理控制器。
這裏寫圖片描述
圖8:SEDA線程池控制器:此圖顯示了在運行Haboob Web服務器期間線程池控制器的操作,如第5.1節中所述。 控制器根據相應事件隊列的長度調整每個階段的線程池的大小。 在此運行中,隊列長度每2秒採樣一次,如果隊列超過100個條目,則會將一個線程添加到池中(每個階段的最大限制爲20個線程)。當線程空閒超過5秒時,它們將從池中刪除。 異步文件階段使用10個隊列條目的控制器閾值來誇大控制器的行爲。
這裏寫圖片描述
圖9:SEDA批處理控制器:該圖顯示了批處理控制器對簡單基準測試的操作,該基準測試包括以振盪速率生成事件的單個階段。 這導致測量的輸出速率變化,如圖的頂部所示。當輸出速率增加時,控制器會降低批處理因子。當輸出速率降低時,控制器會增加批處理因子。在輸出速率突然下降之後,批處理因子被重置爲其最大值。
      這些機制代表了SEDA中動態控制的兩個簡單例子。可以將更復雜的控制器引入系統中; 例如,控制器可能會根據階段優先級的全局概念調整線程池大小,或者將整個系統中的線程數保持在某個閾值以下。另一種選擇是根據階段的進展調整線程調度參數,如Steere等人提出的。[51]。 SEDA異步套接字庫(將在下一節中介紹)包含一個可選控制器,用於限制從網絡讀取數據包的速率 在5.1節中,我們描述了一個特定於應用程序的控制器,它可以自適應地減少負載以滿足響應時間目標。SEDA的結構有助於檢查和控制底層應用,並且該模型可以實現一系列控制策略。
      SEDA中動態控制的一個重要方面是它允許應用程序適應不斷變化的條件,儘管底層操作系統使用了特定的算法。從某種意義上說,SEDA的控制器對操作系統的資源管理策略很天真。例如,SEDA批處理控制器不知道OS線程調度策略; 相反,它會影響基於應用程序性能的外部觀察的線程調度。 雖然在某些情況下可能需要對底層操作系統施加更多控制 - 例如,爲特定階段或線程提供服務質量保證 - 我們認爲商用操作系統提供的基本資源管理機制,取決於應用級別控制,足以滿足互聯網服務的需求。

3.5 Sandstorm:SEDA原型

      我們已經實施了一個名爲Sandstorm的基於SEDA的互聯網服務平臺。Sandstorm完全用Java實現,並使用一組native庫來實現非阻塞套接字I/O(如第4節所述)。使用最新的Java實現,加上正確地使用Java的語言功能,我們發現使用Java的軟件工程的穩定性優勢遠遠超過了性能權衡。例如,我們依靠Java的自動內存管理來在系統內對“過期”事件進行垃圾收集; 這大大簡化了代碼,因爲組件不負責跟蹤事件的生命週期。Java和靜態編譯語言之間的性能差距也在縮小; 事實上,我們基於Java的SEDA Web服務器優於在C中實現的兩個流行的Web服務器,如第5.1節所述。
      在Sandstorm中,每個應用程序模塊都使用單個方法調用handleEvents()實現一個簡單的事件處理程序接口,該方法處理從階段的傳入事件隊列中提取的一批事件。應用程序不創建或管理線程; 這是運行時系統和相關控制器的責任。Sandstorm提供了一個線程管理器接口,可以對其進行定製以實現各種線程分配和調度策略; 此處描述的版本管理每個階段的線程池,並依賴於底層操作系統進行調度。 Sandstorm提供用於命名,創建和銷燬階段,執行隊列操作,控制隊列閾值以及分析和調試的API。下一節中描述的套接字和文件I/O機制被提供爲標準接口。
      Sandstorm運行時由19934行代碼和7871非註釋源語句(NCSS)組成。其中,3023 NCSS專用於核心運行時,2566專用於I/O設施。

4異步I/O原語

      要滿足SEDA支持高併發性的目標,需要高效,強大的I/O接口。本節描述如何使用SEDA概念使用現有OS原語實現這些接口。我們描述了一個異步網絡套接字層,它利用操作系統提供的非阻塞I/O,以及使用阻塞OS調用和線程池來暴露非阻塞行爲的異步文件I/O層。這兩個層都實現爲一組SEDA階段,應用程序可以使用它們來提供快速的異步I/O.

4.1異步套接字I / O.

      Sandstorm異步套接字(asyncSocket)層爲服務提供了易於使用的非阻塞套接字接口。 應用程序創建類asyncClientSocket和asyncServerSocket的實例以啓動傳出和傳入套接字連接。建立連接時,會將asyncConnection對象推送到用戶提供的事件隊列(通常是與請求階段關聯的隊列)。傳入的數據包被排入用戶的事件隊列,asyncConnection實現了一個可以放置傳出數據包的隊列接口。每個輸出包還可以具有相關聯的事件隊列,當包被傳輸時,一個完成事件被推到這個隊列上。錯誤和其他通知事件以類似的方式傳遞給用戶。
      在內部,asyncSocket層使用三個階段實現,這三個階段在所有套接字之間共享,如圖10所示.readStage讀取網絡數據包並響應用戶請求以在新套接字上啓動數據包讀取。writeStage將數據包寫入網絡並建立新的傳出連接。 listenStage接受新的TCP連接並響應用戶監聽新端口的請求。asyncConnection,asyncClientSocket或async-ServerSocket上的每個操作都將轉換爲請求並放置到相應階段的請求隊列中。
這裏寫圖片描述
圖10:基於SEDA的異步套接字層:Sandstorm套接字接口包括三個階段:讀取,寫入和監聽。讀取階段響應網絡I/O就緒事件並從套接字讀取數據,將新數據包推送到應用程序階段。寫入階段接受傳出數據包並調度它們以寫入適當的套接字。它還建立新的傳出套接字連接。listen階段接受新的TCP連接並將連接事件推送到應用程序。
      每個asyncSocket階段都爲兩個獨立的事件隊列提供服務:來自用戶的請求隊列,以及來自操作系統的I/O 就緒/完成事件隊列。 每個階段中的線程交替地爲每個隊列服務,使用簡單的超時機制在兩者之間切換。I/O事件隊列實現爲庫,該庫導致出隊操作調用適當的OS調用以檢索I/O事件。我們當前的實現支持標準的UNIX poll(2)系統調用以及用於事件傳遞的/dev/poll [46]接口。 native庫用於在Java [60]中提供非阻塞套接字調用。爲了提高套接字的公平性,每個階段隨機化處理操作系統提供的I/O事件的順序。這是必要的,因爲OS通常以固定順序(例如,按文件描述符的遞增順序)返回套接字事件。
      只要I/O就緒事件指示套接字具有可用數據,readStage就會通過執行套接字讀取來進行操作。它最多將16 KB讀入預先分配的緩衝區,並將生成的數據包排入用戶提供的事件隊列中。在I/O錯誤的情況下(例如,因爲對等方已關閉連接),該階段關閉套接字並將適當的通知事件推送給用戶。每個套接字讀取都需要分配新的數據包緩衝區;雖然這可能會導致大量的垃圾收集開銷,但我們並未發現這是一個性能問題。請注意,由於此係統是用Java實現的,因此不需要顯式釋放過期的數據包。readStage還提供了一個可選的速率控制器,可以限制從網絡讀取數據包的速率;該控制器可用於在過載條件下執行減載。通過計算輸入包速率的移動平均值並將人工延遲引入事件處理循環以實現特定速率目標來實現控制器。
      writeStage接收來自用戶的數據包寫入請求,並將它們排入與特定套接字關聯的內部隊列。當操作系統指示套接字已準備好寫入時,它會嘗試在該套接字的傳出隊列上寫入下一個數據包。如第5.2節所述,可以對套接字隊列進行閾值處理,以防止“慢”套接字在服務器中佔用過多資源。
      爲了評估asyncSocket的性能,我們實現了一個簡單的服務器應用程序,它接受來自多個客戶端的8KB突發數據包,每1000個突發數據包響應一個32字節的ACK。這種有點人爲的應用程序旨在強調網絡層,並隨着客戶端數量的增加來衡量其可擴展性。圖11顯示了服務器的總吞吐量,期間客戶端數量從1增加到8192.服務器和客戶端計算機都是使用運行Linux 2.2.14和IBM JDK 1.3的千兆以太網互連的4路500 MHz Pentium III系統。
這裏寫圖片描述
圖11:異步套接字層性能:此圖顯示了基於SEDA異步套接字層作爲併發連接數量的函數的性能。每個客戶端打開與服務器的連接併發出8KB突發數據包; 服務器對每個1000個數據包的突發,響應一個32字節的單獨ACK。所有機器都通過交換式千兆以太網連接,並運行Linux 2.2.14。基於SEDA的服務器使用操作系統提供的非阻塞I/O原語。將性能與使用阻塞套接字和多個線程來模擬異步I/O的兼容性層進行比較。基於線程的層無法接受超過400個併發連接,因爲所需的線程數將超過Linux中的每用戶線程限制。
      套接字層的兩種實現方式。 基於SEDA的層使用OS提供的非阻塞I/O和/dev/poll事件傳遞機制[46]。 將其與使用阻塞套接字的兼容性層和用於模擬異步I/O的線程池進行比較。該層爲每個連接創建一個線程來處理套接字讀取事件和一個固定大小的120個線程池來處理套接字寫入。此兼容層最初是爲了在Java下提供異步I / O而開發的,它不直接提供此功能。
      非阻塞實現明顯優於線程版本,隨着連接數量的增加,線程版本迅速降級。實際上,當接收超過400個連接時,線程實現會崩潰,因爲所需的線程數超過了Linux中的每用戶線程限制。非阻塞層的輕微吞吐量降低部分是由於Linux網絡堆棧缺乏可擴展性。即使使用高度優化的/dev/poll機制[46]進行套接字I/O事件通知,隨着套接字數量的增加,來自操作系統的輪詢準備事件所涉及的開銷也會顯着增加[29]。

4.2異步文件I/O.

      Sandstorm文件I/O(asyncFile)層展示與asyncSocket非常不同的設計點。由於底層操作系統不提供非阻塞文件I/O原語,因此我們不得不利用阻塞I/O和有界線程池來實現該層.3用戶通過asyncFile對象執行文件I/O,該對象支持熟悉的接口讀,寫,尋找,統計和關閉。這些操作中的每一個都轉換爲asyncFile階段的事件隊列中的請求。asyncFile線程將每個請求出列並對文件執行相應的(阻塞)I/O操作。 爲確保對同一文件上的多個I/O請求進行串行執行,一次只有一個線程可以處理特定文件的事件。當I/O請求完成時,相應的完成事件將排入用戶的事件隊列。
      asyncFile階段在其線程池中使用單個線程進行初始化。 SEDA線程池控制器負責根據觀察到的併發需求動態調整線程池的大小。圖8顯示了在運行第5.1節中描述的基於SEDA的Web服務器期間工作的線程池控制器。運行分爲三個階段,每個階段對應越來越多的客戶;請注意,客戶端負載是非常突發的。隨着文件訪問的突發到來,控制器將線程添加到每個階段的線程池,直到最多20個線程飽和。在這之間,不需要I / O,並且線程池縮小。雖然PageCache和CacheMiss階段需要更多線程且客戶端負載增加,但服務文件I / O所需的線程數實際上會減少。這是因爲底層文件系統緩衝區緩存正在預熱,並且能夠更快地爲磁盤請求提供服務。線程池控制器推斷出需要更少的線程來管理磁盤併發,並避免創建不需要的線程。

5應用和評估

      在本節中,我們將介紹兩個應用程序的性能和負載調節評估:Haboob,一個高性能的HTTP服務器; 和Gnutella對等文件共享網絡的數據包路由器。 Haboob代表客戶端發出請求並等待響應的“閉環”服務器,而Gnutella數據包路由器是一個“開環”服務器的例子,其中服務器性能不會成爲提供負載的限制因素。

5.1 Haboob:高性能HTTP服務器

      Web服務器構成了可擴展的Internet服務的原型組件。許多先前的工作已經研究了構建高性能HTTP服務器的工程方面,但很少有關於負載調節,穩健性和易於構造的說法。研究HTTP服務器的一個好處是,存在各種行業標準的基準來衡量它們的性能。我們選擇了SPECweb99基準套件[50]中的負載模型作爲我們測量的基礎,並進行了兩項重要修改。首先,我們僅測量靜態網頁訪問的性能(構成SPECweb99負載混合的70%)。其次,我們將網頁文件集固定爲3.31 GB的磁盤文件,對應於SPECweb99目標負載1000個連接。文件大小從102到921600字節,可以使用SPECweb99規定的基於Zipf的請求分發進行訪問。更多細節可以在[50]中找到。

5.1.1 Haboob架構

      Haboob的整體結構如圖5所示。服務器包含10個階段,其中4個階段專門用於異步套接字和磁盤I/O,如上一節所述。HttpParse階段負責接受新的客戶端連接和傳入數據包的HTTP協議處理。 HttpRecv階段接受HTTP連接並請求事件並將它們傳遞到PageCache階段(如果它們代表磁盤文件)或直接生成響應(對於爲收集服務器統計信息而生成的動態頁面)。 PageCache實現了使用哈希表實現的內存中網頁緩存。
      Haboob的整體結構如圖5所示。服務器包含10個階段,其中4個階段專門用於異步套接字和磁盤I/O,如上一節所述。HttpParse階段負責接受新的客戶端連接和傳入數據包的HTTP協議處理。HttpRecv階段接受HTTP連接並請求事件並將它們傳遞到PageCache階段(如果它們代表磁盤文件)或直接生成響應(對於爲收集服務器統計信息而生成的動態頁面)。PageCache實現了一個使用由URL索引的哈希表實現的內存網頁緩存,其中每個條目包含一個由HTTP頭和Web頁面有效負載組成的響應數據包。CacheMiss階段負責處理頁面緩存未命中,使用異步文件I/O層從磁盤讀取所請求頁面的內容。最後,HttpSend向客戶端發送響應並處理連接管理和統計信息收集的某些方面。另一個階段(圖中未顯示)從HTML模板生成動態Web頁面,嵌入的代碼用Python腳本語言編寫[36]。此功能提供了通用的服務器端腳本,類似於Java Server Pages [26]。
      頁面緩存嘗試將緩存大小保持在給定閾值以下(對於下面提供的測量,設置爲204800 KB)。它積極地回收容量未命中的緩衝區,而不是允許舊的緩衝區被Java運行時垃圾收集; 我們發現這種方法可以產生明顯的性能優勢。緩存階段使用特定於應用程序的事件調度來提高性能。特別是,它實現了最短連接優先(SCF)[15]調度,它重新排序請求流以在較長的緩存條目之前發送短緩存條目,並優先考慮緩存命中而不是未命中。由於SCF僅應用於批處理控制器提供的每組事件,因此跨請求的飢餓不是問題。
      將Haboob構建爲一組階段極大地提高了設計的模塊性,因爲每個階段都體現了一個強大的,可重複使用的軟件組件,可以單獨調節負載。 我們能夠測試頁面緩存的不同實現,而無需對其餘代碼進行任何修改; 運行時只是實例化一個不同的階段來代替原始頁面緩存。同樣,另一位沒有Haboob結構知識的開發人員能夠花很少的工作將Haboob使用異步文件層替換爲備用文件系統接口。不包括Sandstorm平臺,Web服務器代碼僅包含3283個非註釋源語句,其中676個NCSS專用於HTTP協議處理庫。

5.1.2基準配置

      爲了進行比較,我們提供了來自流行的Apache [6] Web服務器(版本1.3.14,與Linux Red Hat 6.2系統一起提供)以及Rice大學的Flash [44] Web服務器的性能測量。Apache使用150個進程的固定大小的進程池; 每個進程一次管理一個連接,從磁盤讀取文件數據並使用阻塞I/O操作以8 KB塊的形式將其發送到客戶端。Flash使用高效的事件驅動設計,單個進程處理大多數請求處理任務。一組幫助程序進程執行(阻止)磁盤I/O,路徑名解析和其他操作。Flash靜態頁面緩存的最大大小設置爲204800 KB,與Haboob中的大小相同。Apache和Flash都是用C實現的,而Haboob是用Java實現的。
      以下所有測量均在服務器上運行,該服務器運行在具有2 GB RAM和Linux 2.2.14的4路SMP 500 MHz Pentium III系統上。IBM JDK v1.3.0用作Java平臺。32臺具有類似配置的機器用於生成負載,每臺客戶機使用多個線程來模擬許多實際客戶機。所有機器都通過交換式千兆以太網互連。雖然這種配置不能模擬廣域網效果,但我們感興趣的是服務器在高負載下的性能和穩定性。
      客戶端負載生成器循環,不斷請求網頁(使用SPECweb99套件指定的分發),讀取結果,並在請求下一頁之前休眠20毫秒的固定時間。 爲了更密切地模擬廣域中客戶端的連接行爲,每個客戶端在5個HTTP請求之後關閉TCP連接,並在繼續之前重新建立連接。該值是根據[39]的HTTP流量觀察結果選擇的。所有基準測試均使用熱文件系統和網頁緩存運行。請注意,3.31 GB的文件集大小遠遠大於物理內存,Haboob和Flash的靜態頁面緩存僅設置爲200 MB; 因此,這些測量包括大量的磁盤I/O.

5.1.3性能分析

      圖12顯示了Haboob與Apache和Flash在聚合吞吐量和響應時間方面的性能。還顯示了每個客戶完成的請求數量的the Jain fairness index(公平指數)[27]。 該指標定義爲
這裏寫圖片描述
其中xi是每N個客戶端的請求數。公平指數爲1表示服務器對所有客戶端同等公平; 較小的值表示較不公平。直觀地,如果N個客戶端中的k個接收到相等的服務份額,而其他N-k個客戶端不接收服務,則Jain公平性指數等於k/N.(維基)
      如圖12(a)所示,Haboob的吞吐量隨着客戶端數量的增加而趨於穩定,爲1024個客戶端維持超過200 Mbps。Flash和Apache也表現出穩定的吞吐量,儘管略低於Haboob。這個結果可能看起來令人驚訝,因爲我們所期望的基於進程的Apache服務器的性能隨着客戶端數量的增加而降低。但是,回想一下Apache服務器在任何時間只接受不超過150個客戶端的連接,因而基於進程的高併發量並不難維持。當數量客戶超過這個數量,所有其他客戶在被系統接受之前,必須等待越來越長的時間。Flash有類似的問題:它限制了同時連接的數量506,由於可以使用 select() 系統調用的文件描述符的數量限制。當服務器飽和時,客戶端必須在建立連接之前等待很長一段時間。
      圖12(b)顯示了這種效果,它顯示了具有1024個客戶端的每個服務器響應時間的累積分佈。這裏,響應時間定義爲服務器響應給定請求的總時間,包括建立TCP連接的時間(如果尚未建立)。儘管所有三臺服務器的平均響應時間大致相同,但分佈卻非常不同。Apache和Flash顯示出比Haboob更快的低響應時間分佈,但是有很長的尾巴,有相當大比例的請求超過幾十秒。 請注意,圖中對數刻度的使用不會強調尾部的長度。 Apache的最大響應時間超過93秒,Flash的響應時間超過37秒。響應時間的長尾是由建立新連接的TCP重傳定時器的指數後退引起的,在Linux下,這個時間可以增長到120秒。
      使用Apache,如果客戶端是“幸運的”,則可以快速接受其連接,並且所有請求都由單個服務器進程處理。此外,每個進程僅與149個其他進程競爭,這在大多數系統上都是可管理的流程。這解釋了大量的低響應時間。但是,如果客戶端“不幸運”,則必須等待服務器進程可用; TCP重新傳輸退避意味着此等待時間可能變得非常大。這種對客戶的不平等待遇反映在Apache的公平度量值較低。
      使用Flash,所有客戶端都可以非常快速地接受到系統中,並且在服務器內受到排隊延遲的影響。Flash中的低響應時間主要歸功於非常有效的實現。包括快速HTTP協議處理庫; 我們在Haboob中進行了一些優化。 但是,Flash一次只接受506個連接的事實意味着在高負載下TCP退避成爲一個問題,導致響應時間分佈的長尾。
      相比之下,Haboob在超載時對客戶表現出極大的公平性。 平均響應時間爲547毫秒,最大值爲3.8秒。這符合我們優雅降級的目標 - 當服務器過載時,不應該以任意等待時間不公平地懲罰等待請求。Haboob迅速接受新的客戶端連接,並允許請求在應用程序中排隊,在它們在階段之間傳遞時,它們得到公平的服務。 因此,服務可以看到負載,允許應用各種負載調節策略。例如,爲了提供差異化服務,有必要有效地接受連接以進行檢查。這裏的權衡是在低平均響應時間與響應時間的低方差之間。 在Haboob,我們選擇了後者。
這裏寫圖片描述
圖12:Haboob Web服務器性能:該圖顯示了Haboob Web服務器與Apache和Flash相比的性能。(a)顯示每個服務器使用3.31 GBytes的文件集的吞吐量,因爲客戶端數量從1增加到1024.還顯示了每個服務器提供的Jain公平性指數。公平指數爲1表示服務器對所有客戶端同等公平; 較小的值表示較不公平。(b)顯示1024個客戶端的響應時間的累積分佈函數。 雖然Apache和Flash表現出高頻率的低響應時間,但尾部很重,最大響應時間相當於幾分鐘。

5.1.4自適應減載

      在本節中,我們評估Haboob在過載下的行爲,並演示使用特定於應用程序的控制器,該控制器試圖通過減載將響應時間保持在給定閾值以下。在此基準測試中,每個客戶端都會重複請求一個動態Web頁面,該頁面需要生成大量的I/O和計算。通過使每個服務器受到大量這些“瓶頸”請求,我們通常可以產生比服務靜態網頁時更大的負載。
      對於每個請求,服務器執行循環的多次迭代,該循環打開文件,從中讀取數據,並生成數據的總和。在此處理之後,服務器向客戶端返回8 KB響應。在Apache中,這是作爲在Apache服務器進程的上下文中運行的Perl模塊實現的。在Flash中,使用了提供的“快速CGI”接口,它創建了許多(持久的)服務器進程來處理動態請求。當發出CGI請求時,使用空閒服務器進程來處理請求,或者如果沒有空閒服務器進程則創建新進程。在Haboob中,瓶頸被實現爲一個單獨的階段,允許線程池控制器確定專用於階段處理的線程數,並在階段的傳入事件隊列中使用閾值來拒絕超額負載。由於這三種實現之間的差異,通過調整動態頁面生成所執行的工作量,使服務器端每個請求延遲40毫秒。
      圖13顯示了具有1024個客戶端的三臺服務器的響應時間的累積分佈。 Apache和Haboob每個都表現出很大的響應時間,但原因各不相同。 Apache的響應時間尾部是由TCP重新傳輸退避引起的,如上所述,並且只有150個併發進程,服務器內的排隊延遲最小。在Haboob中,在任何給定時間內,最多1024個併發請求在服務器內排隊,導致瓶頸處的大排隊延遲。 Flash的明顯低響應時間是由於其CGI處理代碼中的錯誤導致它在無法派生(fork)新的CGI進程時過早地關閉連接。對於1024個客戶端,系統中一次最多可以有1024個CGI進程;與其他Flash進程一起,這超出了Linux中的每用戶進程限制。當fork失敗時,Flash會立即關閉客戶端連接,而不會向客戶端返回任何響應(甚至是錯誤消息)。在此次運行中,超過74%的請求導致過早關閉連接。
      這種機制提出了一種有效的方法來限制服務器中請求的響應時間:即,當服務器檢測到它過載時自適應地減少負載。 爲了證明這一想法,我們在瓶頸階段構建了一個特定於應用程序的控制器,它可以觀察通過該階段的請求的平均響應時間。 當響應時間超過5秒的閾值時,控制器會以指數方式降低階段的隊列閾值。 當響應時間低於閾值時,控制器將隊列閾值增加固定量。 當HttpRecv階段無法將新請求存入瓶頸階段的事件隊列時(因爲已超過隊列閾值),將向客戶端返回錯誤消息。 請注意,這只是減載政策的一個例子; 替代方案是將HTTP重定向發送到服務器場中的另一個節點,或者提供降級服務。
      圖13顯示了啓用響應時間控制器的累積響應時間分佈。 在這種情況下,控制器有效地減少了通過服務器的請求的響應時間,90%的請求表現出低於11.8秒的響應時間,最大響應時間僅爲22.1秒。 在此次運行中,由於隊列閾值處理,98%的請求被服務器拒絕。 請注意,此控制器無法保證響應時間低於目標值,因爲隊列閾值較高時發生的突發可能會導致客戶端響應時間出現峯值。
這裏寫圖片描述
圖13:響應時間控制器:此圖顯示了特定於應用程序的控制器的影響,該控制器釋放負載以使響應時間保持在目標值以下。這裏,1024個客戶端重複請求動態Web頁面,該Web頁面需要生成I/O和計算。Apache和Haboob(with no control)處理所有這些請求,導致大的響應時間。 由於CGI處理代碼中的錯誤,Flash拒絕了大量請求; 客戶端永遠不會被告知服務器正忙。 啓用響應時間控制器後,當平均響應時間超過5秒的閾值時,Haboob會拒絕帶有錯誤消息的請求。

5.2 Gnutella數據包路由器

      我們選擇實現Gnutella數據包路由器來演示SEDA在非傳統互聯網服務中的使用。Gnutella路由器代表了一種與HTTP服務器完全不同的服務方式:在對等文件共享網絡中的參與者之間路由數據包。像Gnutella這樣的服務的重要性日益增加,因爲新的分佈式應用程序的開發是爲了利用廣域內主機的良好連接性。對等模型已被多個分佈式存儲系統採用,如Freenet [14],OceanStore [30]和Intermemory [13]。
      Gnutella [19]允許用戶搜索和下載來自其他Gnutella用戶的文件。該協議完全去中心化的;運行Gnutella客戶端的節點形成一個通過TCP/IP分層的adhoc多跳路由網絡,節點通過將收到的消息轉發給它們的相鄰節點來進行通信。Gnutella節點傾向於同時連接到幾個(通常是四個或更多)其他節點,並且網絡上節點的初始發現是通過衆所周知的主機完成的。Gnutella中有五種消息類型:ping用於發現網絡上的其他節點; pong是對ping的迴應; query用於搜索其他Gnutella主機服務的文件; queryhits是對查詢的響應;和push用於允許客戶端通過防火牆下載文件。數據包路由器負責向所有其他相鄰接點廣播接收到的ping和查詢消息,並沿着相應的ping或查詢消息的路徑路由pong,queryhits和push消息。有關消息格式和路由協議的詳細信息,請參見[19]。

5.2.1架構

      除了異步套接字I/O層之外,基於SEDA的Gnutella數據包路由器使用3個階段實現。該代碼由1294個非註釋源語句組成,其中880個NCSS專門用於Gnutella協議處理。GnutellaServer階段接受TCP連接並處理數據包,將數據包事件傳遞到GnutellaRouter階段,該階段執行路由表的實際數據包路由和維護。 GnutellaCatcher是用於連接Gnutella網絡的助手階段,它通過聯繫周所周知的站點(well-known site)來接收要連接的主機列表。除了由其他廣域客戶端建立的任何連接之外,它還嘗試保持至少4個同時連接到網絡的連接。加入“實時”Gnutella網絡和路由數據包使我們能夠在真實環境中測試SEDA,以及測量通過路由器的流量。在一個37小時的運行期間,路由器處理了2480萬個數據包(平均每秒179個數據包),並從網絡上的其他主機接收了72,396個連接,在任何給定時間平均有12個同時連接。路由器每秒能夠支持超過20,000個數據包。

5.2.2 防止慢套接字

      我們原始的數據包路由器原型展示了一個有趣的內存泄漏:在通過網絡正確路由數據包幾個小時之後,服務器會在耗盡內存後崩潰。觀察各個階段隊列長度使我們能夠輕鬆地檢測問題的根源:大量的傳出數據包正在排隊等待某些廣域連接,導致隊列長度(因此內存使用)變得無限制。我們測量了Gnutella消息的平均數據包大小約爲32個字節;每秒僅115個數據包的數據包速率可以使28.8千比特的調制解調器鏈路飽和,這仍然是許多Gnutella軟件用戶常用的。在這種情況下,解決方案是對每個套接字的傳出數據包隊列施加一個閾值,並關閉超過其閾值的連接。此解決方案是可以接受的,因爲Gnutella客戶端會自動發現並連接到網絡上的多個主機;跨網絡節點的冗餘意味着客戶端不需要依賴於特定主機來保持連接到網絡。

5.2.3負載調節行爲

      爲了評估SEDA資源控制器在負載調節中的使用,我們在Gnutella路由器中引入了一個故意的瓶頸,其中每個查詢消息都會導致20 ms的服務延遲。這是通過讓應用程序事件處理程序在收到查詢數據包時休眠20毫秒來實現的。 我們實現了一個負載生成客戶端,它連接到服務器並根據與實際Gnutella流量相近的分佈生成數據包流。在我們的Gnutella流量模型中,查詢消息構成了生成數據包的15%。使用單個線程執行數據包路由,很明顯,隨着流入服務器的數據包數量的增加,此延遲將導致其他消息的大量積壓。
      圖14(a)顯示了ping和查詢數據包通過服務器的平均延遲,提供的負載從100到1000包/秒增加。客戶端和服務器計算機使用與HTTP服務器基準測試中相同的配置。當提供的負載超過服務器的容量時,數據包延遲會急劇增加。在1000個數據包/秒的情況下,服務器崩潰(由於內存不足以緩衝傳入的數據包),然後才能進行延遲測量。
      此時,可以採用若干負載調節策略。一個簡單的策略是對每個階段的傳入事件隊列進行閾值處理,並在超過閾值時丟棄數據包。或者,可以使用類似於隨機早期檢測(RED)擁塞避免方案[17]中使用的方法,其中基於輸入隊列的長度概率地丟棄數據包。雖然這些策略會導致許多數據包在過載期間被丟棄,但由於Gnutella網絡流量的有損性質,這可能是一種可接受的解決方案。另一種策略是允許所有數據包進入系統,但讓應用程序事件處理程序過濾掉查詢數據包(這是過載的來源)。另一個策略是利用asyncSocket輸入速率控制器將進入的數據包速率限制在系統中。
      另一種方法是利用SEDA的資源控制器自動克服瓶頸。 在這種方法中,線程池控制器在檢測到需要額外的併發時將線程添加到GnutellaRouter階段; 這種機制類似於基於集羣的TACC [18]系統中的動態工作者分配。圖14(b)顯示了啓用SEDA線程池控制器的Gnutella路由器的平均延遲。如圖14(c)所示,2個線程被添加到GnutellaRouter線程池中,允許服務器處理增加的數據包負載,儘管存在瓶頸。這個數字與從Little的結果中獲得的理論值相匹配:如果我們將階段建模爲具有n個線程的排隊系統,平均數據包到達率爲λ,查詢數據包頻率爲p,查詢服務延遲爲L秒, 那麼維持λ完成率所需的線程數是n =λpL=(1000)(0.15)(20 ms)= 3個線程。
這裏寫圖片描述
圖14:Gnutella數據包路由器延遲:這些圖顯示了隨着傳入包率的增加,ping和query包通過Gnutella包路由器的平均延遲時間。Query數據包(15%數據包混合)會導致服務器端延遲20 ms。(a)顯示了單個線程處理數據包的延遲。請注意,隨着提供的負載超過服務器容量,延遲會急劇增加;在1000個數據包/秒時,服務器在進行延遲測量之前內存不足。(b)顯示啓用線程池控制器的延遲。請注意,對於100和200數據包/秒,沒有線程被添加到應用程序階段,因爲事件隊列從未達到其閾值。這解釋了與400和1000包/秒相比較高的數據包延遲,其中2個線程被添加到該階段。(c)顯示GnutellaRouter隊列長度隨時間的變化,負載爲1000包/秒,線程池控制器處於活動狀態。控制器在指示的兩個點中的每個點處向階段添加了一個線程。

6討論和結論

      因特網服務引發了一系列新的系統設計要求,因爲必須以強大,易於編程的方式提供大規模併發,以便優雅地處理負載的巨大變化。 SEDA是爲該制度建立設計原則的一步。在本文中,我們介紹了SEDA設計和執行模型,介紹了由顯式事件隊列連接的階段的概念。SEDA利用一組動態控制器來管理每個階段的資源使用和調度; 我們已經描述了幾個控制器,包括兩個跨階段的控制線程分配和一個階段內部使用的批處理程度。我們還分析了兩個高效的異步I/O組件,以及使用SEDA設計構建的兩個應用程序,表明SEDA在負載下表現出良好的性能和穩健的行爲。
      SEDA模型在互聯網服務設計領域開闢了新的問題。顯式事件隊列和動態資源控制器的使用提高了專門針對服務進行調整的新穎調度和資源管理算法的可能性。作爲未來的工作,我們計劃實施一個廣義的流量控制方案,用於各階段之間的通信; 在此方案中,每個事件都需要一定數量的信用才能排入目標階段的事件隊列。 通過爲每個事件分配可變數量的信用,可以實現有趣的負載調節策略。
      我們認爲,測量和控制是繁忙的互聯網服務中資源管理和過載保護的關鍵。這與基於資源遏制的長期存在的方法形成對比,後者爲系統中的每個任務(例如進程,線程或服務器請求)分配固定資源,並努力控制每個任務消耗的資源。儘管這些技術在互聯網服務中提供差異化服務方面已經取得了一些成功[57],但是遏制通常要求對每項任務進行先驗的資源分配,從而限制了適用的負載調節策略的範圍。相反,我們認爲動態資源控制,加上面對過載的特定應用適應,是接近負載調節的正確方法。
      當控制被視爲資源管理的基礎時,會出現兩個新的挑戰。第一個是檢測過載情況:許多變量會影響服務的交付性能,而確定服務實際上是過載的以及原因是一個有趣的問題。第二是確定適當的控制策略來抵抗過載。 我們計劃對當前實施中的資源控制器進行多項改進,以及針對備用指標進行優化的新控制器。 例如,爲了減少資源消耗,可能需要優先考慮釋放資源而不是消耗資源的階段。在SEDA下,控制系統的工作主體[43,45]可以用於服務資源管理,我們只是觸及了這種技術潛力的表面。
      關於事件驅動的併發模型的一個共同關注點是易於編程。現代語言和編程工具支持線程應用程序的開發和調試,許多開發人員認爲事件驅動編程本質上更加困難。事實上,大多數事件驅動的服務器應用程序通常非常複雜,並且在設計上有點特別,這使得這種觀點持續存在。根據我們的經驗,SEDA模型中的編程比多線程應用程序設計和傳統的事件驅動模型更容易。當線程被隔離到單個階段時,線程同步和競爭條件等問題更易於管理。階段之間面向消息的通信建立了明確的排序;在傳統的事件驅動設計中,通過系統跟蹤事件流程要困難得多。我們認爲SEDA是線程和事件驅動設計之間的理想中間點,對編程模型的進一步探索是未來工作的重要方向。
      雖然SEDA有助於在商品操作系統上構建條件良好的服務,但SEDA模型爲操作系統設計提供了新的方向。我們設想一個直接支持SEDA執行模型的操作系統,併爲應用程序提供對調度和資源使用的更大控制。這種方法類似於各種研究系統[5,11,28,34]中提供的方法,可以實現特定於應用程序的資源管理。更爲根本的是,基於SEDA的操作系統無需設計爲允許多個應用程序透明地共享資源。Internet服務是高度專業化的,並不是爲了與其他應用程序共享機器而設計的:例如,Web服務器通常不希望與數據庫引擎在同一臺機器上運行(更不用說科學計算或文字處理器)。儘管操作系統可以實施保護(以防止一個階段破壞內核狀態或另一個階段),但系統不需要以掩蓋應用程序可用性的方式虛擬化資源。
致謝
該研究得到了國防高級研究計劃局(DABT63-98-C-0038和N66001-99-2-8913),國家科學基金會(授權EIA-9802069),英特爾公司,北電網絡和 Royal Philips Electronics。Matt Welsh得到了美國國家科學基金會研究生獎學金的支持。 我們要感謝Steve Gribble,Joe Hellerstein和Marti Hearst對本文的寶貴意見。Eric Fraser,Matt Massie,Albert Goto和Philip Buonadonna爲用於獲得性能測量的Berkeley Mil-lennium集羣提供了支持。Eric Wagner在Haboob Web服務器中提供了服務器端腳本功能。 我們特別感謝我們的指導者Andrew Myers和匿名審稿人的有益評論。
References
[1] Akamai, Inc. http://www.akamai.com/.
[2] America Online Press Data Points. http://corp.aol.com/press/
press_datapoints.html.
[3] DigitalIsland,Inc.http://www.digitalisland.com/.
[4] Acme Labs. thttpd: Tiny/Turbo/Throttling HTTP Server. http://www. acme.com/software/thttpd/.
[5] T. Anderson, B. Bershad, E. Lazowska, and H. Levy. Scheduler activa- tions: Effective kernel support for the user-level management of paral- lelism. ACM Transactions on Computer Systems, 10(1):53–79, February 1992.
[6] Apache Software Foundation. The Apache web server. http://www. apache.org.
[7] G. Banga, P. Druschel, and J. Mogul. Resource containers: A new facility for resource management in server systems. In Proc. Third Symposium on Operating Systems Design and Implementation (OSDI ’99), February 1999.
[8] G.BangaandJ.C.Mogul.ScalablekernelperformanceforInternetservers under realistic loads. In Proc. 1998 Annual Usenix Technical Conference, New Orleans, LA, June 1998.
[9] G. Banga, J. C. Mogul, and P. Druschel. A scalable and explicit event delivery mechanism for UNIX. In Proc. USENIX 1999 Annual Technical Conference, Monterey, CA, June 1999.
[10] BEA Systems. BEA WebLogic. http://www.beasys.com/ products/weblogic/.
[11] B. Bershad, S. Savage, P. Pardyak, E. G. Sirer, D. Becker, M. Fiuczyn- ski, C. Chambers, and S. Eggers. Extensibility, safety and performance in the SPIN operating system. In Proc. 15th ACM Symposium on Operating System Principles (SOSP-15), 1995.
[12] A. Chankhunthod, P. B. Danzig, C. Neerdaels, M. F. Schwartz, and K. J. Worrell. A hierarchical Internet object cache. In Proc. 1996 Usenix Annual Technical Conference, pages 153–163, January 1996.
[13] Y. Chen, J. Edler, A. Goldberg, A. Gottlieb, S. Sobti, and P. Yianilos. A prototype implementation of archival Intermemory. In Proc. Fourth ACM Conference on Digital Libraries (DL ’99), Berkeley, CA, 1999.
[14] I. Clarke, O. Sandberg, B. Wiley, , and T. W. Hong. Freenet: A dis- tributed anonymous information storage and retrieval system in designing privacy enhancing technologies. In Proc. ICSI Workshop on Design Issues in Anonymity and Unobservability, Berkeley, CA, 2000.
[15] M. Crovella, R. Frangioso, and M. Harchol-Balter. Connection scheduling in Web servers. In Proc. 1999 USENIX Symposium on Internet Technolo- gies and Systems (USITS ’99), October 1999.
[16] M.L.Dertouzos.Thefutureofcomputing.ScientificAmerican,July1999.
[17] S. Floyd and V. Jacobson. Random early detection gateways for conges- tion avoidance. IEEE/ACM Transactions on Networking, 1(4):397–413, August 1993.
[18] A. Fox, S. D. Gribble, Y. Chawathe, E. A. Brewer, and P. Gauthier. Cluster- based scalable network services. In Proc. 16th ACM Symposium on Oper- ating Systems Principles, St.-Malo, France, October 1997.
[19] Gnutella.http://gnutella.wego.com.
[20] S. Gribble, E. Brewer, J. Hellerstein, and D. Culler. Scalable, distributed data structures for internet service construction. In Proc. Fourth Sympo- sium on Operating Systems Design and Implementation (OSDI 2000), Oc- tober 2000.
[21] S. Gribble, M. Welsh, R. von Behren, E. Brewer, D. Culler, N. Borisov, S. Czerwinski, R. Gummadi, J. Hill, A. Joseph, R. Katz, Z. Mao, S. Ross, and B. Zhao. The Ninja architecture for robust Internet-scale systems and services. Computer Networks, June 2000. Special Issue on Pervasive Com- puting.
[22] Hewlett-Packard Corporation. e-speak Open Services Platform. http: //www.e-speak.net/.
[23] J. Hu, S. Mungee, and D. Schmidt. Techniques for developing and mea- suring high-performance Web servers over ATM networks. In Proc. IN- FOCOM ’98, March/April 1998.
[24] J. C. Hu, I. Pyarali, and D. C. Schmidt. High performance Web servers on Windows NT: Design and performance. In Proc. USENIX Windows NT Workshop 1997, August 1997.
[25] IBM Corporation. IBM WebSphere Application Server. http:// www-4.ibm.com/software/webservers/.
[26] S. M. Inc. Java Server Pages API. http://java.sun.com/ products/jsp.
[27] R.Jain,D.Chiu,andW.Hawe.Aquantitativemeasureoffairnessanddis- crimination for resource allocation in shared computer systems. Technical Report TR-301, DEC Research, September 1984.
[28] M. F. Kaashoek, D. R. Engler, G. R. Ganger, H. M. Bricen ̃o, R. Hunt, D. Mazie`res, T. Pinckney, R. Grimm, J. Jannotti, and K. Mackenzie. Ap- plication performance and flexibility on Exokernel systems. In Proc. 16th ACM Symposium on Operating Systems Principles (SOSP ’97), October 1997.
[29] D. Kegel. The C10K problem. http://www.kegel.com/c10k. html.
[30] J. Kubiatowicz, D. Bindel, Y. Chen, S. Czerwinski, P. Eaton, D. Geels, R. Gummadi, S. Rhea, H. Weatherspoon, W. Weimer, C. Wells, and B. Zhao. OceanStore: An architecture for global-scale persistent storage. In Proc. Ninth international Conference on Architectural Support for Pro- gramming Languages and Operating Systems (ASPLOS 2000), November 2000.
[31] J.LarusandM.Parkes.Usingcohortschedulingtoenhanceserverperfor- mance. Technical Report MSR-TR-2001-39, Microsoft Research, March 2001.
[32] H. Lauer and R. Needham. On the duality of operating system structures. In Proc. Second International Symposium on Operating Systems, IRIA, October 1978.
[33] J. Lemon. FreeBSD kernel event queue patch. http://www. flugsvamp.com/ ̃jlemon/fbsd/.
[34] I.Leslie,D.McAuley,R.Black,T.Roscoe,P.Barham,D.Evers,R.Fair- bairns, and E. Hyden. The design and implementation of an operating system to support distributed multimedia applications. IEEE Journal on Selected Areas in Communications, 14:1280–1297, September 1996.
[35] A. S. Lett and W. L. Konigsford. TSS/360: A time-shared operating sys- tem. In Proc. Fall Joint Computer Conference, Volume 33, Part 1, pages 15–28, 1968.
[36] M.Lutz.ProgrammingPython.O’ReillyandAssociates,March2001.
[37] Microsoft Corporation. DCOM Technical Overview. http: //msdn.microsoft.com/library/backgrnd/html/msdn_ dcomtec.htm.
[38] Microsoft Corporation. IIS 5.0 Overview. http://www. microsoft.com/windows2000/library/howitworks/ iis/iis5techove%rview.asp.
[39] J. C. Mogul. The case for persistent-connection HTTP. In Proc. ACM SIGCOMM’95, October 1995.
[40] R. Morris, E. Kohler, J. Jannotti, and M. F. Kaashoek. The Click modular router. In Proc. 17th ACM Symposium on Operating Systems Principles (SOSP ’99), pages 217–231, Kiawah Island, South Carolina, December 1999.
[41] D. Mosberger and L. Peterson. Making paths explicit in the Scout operat- ing system. In Proc. OSDI ’96, October 1996.
[42] Netscape Corporation. Netscape Enterprise Server. http://home. netscape.com/enterprise/v3.6/index.html.
[43] K.Ogata.ModernControlEngineering.PrenticeHall,1997.
[44] V. S. Pai, P. Druschel, and W. Zwaenepoel. Flash: An efficient and portable Web server. In Proc. 1999 Annual Usenix Technical Conference, June 1999.
[45] S.Parekh,N.Gandhi,J.L.Hellerstein,D.Tilbury,T.Jayram,andJ.Bigus. Using control theory to achieve service level objectives in performance management. In Proc. IFIP/IEEE International Symposium on Integrated Network Management, Seattle, WA, May 2001.
[46] N. Provos and C. Lever. Scalable network I/O in Linux. Technical Report CITI-TR-00-4, University of Michigan Center for Information Technology Integration, May 2000.
[47] X.Qie,A.Bavier,L.Peterson,andS.Karlin.Schedulingcomputationson a software-based router. In Proc. SIGMETRICS 2001, June 2001.
[48] M. Russinovich. Inside I/O completion ports. http://www. sysinternals.com/comport.htm.
[49] O. Spatscheck and L. Petersen. Defending against denial of service at- tacks in Scout. In Proc. 3rd Symposium on Operating Systems Design and Implementation, February 1999.
[50] Standard Performance Evaluation Corporation. The SPECweb99 bench- mark. http://www.spec.org/osg/web99/.
[51] D.C.Steere,A.Goel,J.Gruenberg,D.McNamee,C.Pu,andJ.Walpole. A feedback-driven proportion allocator for real-rate scheduling. In Proc. 3rd Usenix Symposium on Operating Systems Design and Implementation (OSDI’99), pages 145–158, 1999.
[52] Sun Microsystems. RPC: Remote Procedure Call Protocol Specification Version 2. Internet Network Working Group RFC1057, June 1988.
[53] Sun Microsystems Inc. Enterprise Java Beans Technology. http:// java.sun.com/products/ejb/.
[54] Sun Microsystems, Inc. Java Remote Method Invocation. http:// java.sun.com/products/jdk/rmi/.
[55] Sun Microsystems Inc. Jini Connection Technology. http://www. sun.com/jini/.
[56] M. Vandevoorde and E. Roberts. Work crews: An abstraction for control- ling parallelism. Technical Report Research Report 42, Digital Equipment Corporation Systems Research Center, February 1988.
[57] T. Voigt, R. Tewari, D. Freimuth, and A. Mehra. Kernel mechanisms for service differentiation in overloaded Web servers. In Proc. 2001 USENIX Annual Technical Conference, Boston, June 2001.
[58] L. A. Wald and S. Schwarz. The 1999 Southern California Seismic Net- work Bulletin. Seismological Research Letters, 71(4), July/August 2000.
[59] D. A. Wallach, D. R. Engler, and M. F. Kaashoek. ASHs: Application- specific handlers for high-performance messaging. In Proc. ACM SIG- COMM ’96 Conference: Applications, Technologies, Architectures, and Protocols for Computer Communication, pages 40–52, Stanford, Califor- nia, August 1996.
[60] M. Welsh. NBIO: Nonblocking I/O for Java. http://www.cs. berkeley.edu/ ̃mdw/proj/java-nbio.
[61] M. Welsh and D. Culler. Virtualization considered harmful: OS design directions for well-conditioned services. In Proc. 8th Workshop on Hot Topics in Operating Systems (HotOS VIII), Schloss Elmau, Germany, May 2001.
[62] Yahoo! Inc. Yahoo! reports Second Quarter 2001 financial results. http: //docs.yahoo.com/docs/pr/release794.html.
[63] Zeus Technology. Zeus Web Server. http://www.zeus.co.uk/ products/ws/.
原文:https://github.com/mdwelsh/mdwelsh.github.io/blob/master/papers/seda-sosp01.pdf

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