我扮演的關鍵角色之一是在本地社區中傳播Akka。 作為討論的一部分,人們通常會想到的問題/疑問是Akka如何針對編寫良好的Java / JEE應用程序提供更好的可伸縮性和并發性。
由于底層硬件/ JVM保持不變,因此參與者模型如何比傳統的JEE應用程序發揮更多的功能? 為了展示懷疑者,我們決定在現有的JEE Web應用程序中進行小型測試,對業務邏輯進行重新建模以利用參與者模型,并對該模型進行測試。
日交易者應用
DayTrader是圍繞在線股票交易系統范例構建的基準應用程序。 該應用程序允許用戶登錄,查看其投資組合,查找股票報價以及買賣股票。 DayTrader不僅是功能測試的出色應用程序,而且還提供了一組標準的工作負載,用于表征和衡量應用程序服務器和組件級別的性能。
DayTrader建立在一套核心的Java EE技術上,該技術包括用于表示層和Java數據庫連接(JDBC)的Java Servlet和JavaServer Page(JSP),Java消息服務(JMS),企業JavaBeans(EJB)和消息驅動Bean (MDB)用于后端業務邏輯和持久層。 有關DayTrader的更多信息,請點擊這里 。 DayTrader似乎是測試我們理論的應用的合適之選。 我們決定使用JSP-> JDBC模型來使事情保持簡單和可比性。 我們采用了2個用例,并對業務邏輯進行了重新建模以使用TypedActors。
場景1 –報價/交易屏幕–獲取報價
在DayTrader應用程序的“報價/交易者”屏幕中,有一個工具,可通過單擊“報價”按鈕來選擇報價列表的詳細信息。 該股票的報價將被檢索并顯示給用戶。
在標準流程中,獲取報價請求由專用的TradeAction處理,該TradeAction在內部調用TradeDirectJEEE對象的getQuote()接口。 對于每個請求,都會創建一個TradeAction對象。
在更新的流程中,創建了一組工作人員角色,它們偵聽來自各個模塊的請求以獲取報價詳細信息。 TradeActionManager將在開始時創建Typed actor池,并且還將執行將傳入請求路由到Typed actor的操作,Typeed actor包含TradeAction對象以調用getQuote函數。 由于使用了類型化角色,因此相同的TradeActionManager可以在現有應用程序中進行最小的更改的情況下滿足其他TradeAction調用。
原始和修改后的DayTrader應用程序都由20個,50個,75個和100個Typed actor以及許多Trade Action對象執行。
該圖顯示了每種測試方案的相對吞吐量,深紅色的長條表示原始應用程序的吞吐量值,其他長條表示不同角色池大小的Akka應用程序的吞吐量。
- Akka Typed Actor的每秒吞吐量比原始DayTrader應用程序(對于較大的actor池大小)要好,并且具有較少的內存使用(尤其是700和300個用戶*每個請求2個)。
- 原始應用程序需要額外的168 MB來處理1400個請求(700個用戶,每個請求2個請求),而對于Typed Actor池大小為50個actor的修改后的應用程序,用于服務相同類型請求量的額外內存被觀察為104 MB, 提高了38% 。 對于75和100個類型的actor,觀察到額外的內存使用量在126MB-136MB之間。
該圖顯示了每種測試方案的相對吞吐量,深紅色的條表示原始應用程序的吞吐量值,其他條表示不同的參與者池大小使用Akka的應用程序的吞吐量。
使用Jmeter對獲取報價的呼叫模擬是在相同的高負載條件下,分別針對300個用戶,分別針對100個和200個演員的不同系統和Akka設置進行的,大約需要45分鐘。
- 已觀察到,在相同條件下,相對于原始應用程序,將Typed Actor的數量從100增加到200相對可以將吞吐量提高約15%和18%。
- 還可以觀察到,將堆大小增加到1024 MB,并將垃圾回收方法更改為并發標記清除,有助于提高高負載條件下的吞吐量。
方案2 – 4個屏幕–登錄,主頁,獲取報價,購買
嘗試了一個由4個用戶屏幕組成的更復雜的用例,其中用戶將使用四個步驟來完成用例場景。 四個步驟是
- 用戶通過登錄頁面登錄
- 提交登錄憑據后,向用戶顯示主頁。
- 獲取股票的報價,其符號由用戶在主頁屏幕上輸入。
- 在每個符號下方提交要購買的數量后,購買股票。
所有請求都使用TradeAction對象為請求提供服務。 TradeAction對象實現TradeService接口。 因此,在這種情況下,也應用了為報價/交易屏幕實現的相同TypedActor模型–在上一種情況下確定的“獲取報價”業務情景,而且在TradeAction模塊中幾乎沒有或沒有任何更改。
使用Jmeter對包含四個屏幕的用例進行了模擬,為300個具有不同Typed Actor池大小的用戶創建了用例。 用戶數量設置為在60秒內增加到最多300個用戶,并且測試運行了15分鐘。
可以觀察到,將actor的數量從0增加到300可將吞吐量提高大約8%。
超過300個Typed actor的任何增加都顯示出較小的改進。
與原始應用程序的內存使用量相比,使用相同類型的actor的應用程序的峰值內存使用率在相同吞吐量(100個類型化的actor)的情況下提高了約30-40%。
結論
即使進行了簡單的更改,運行在標準筆記本電腦上的應用程序仍能夠提供更好的吞吐量( + 8% ),并且整體內存使用率下降了38% ,這表明actor模型的效率以及Akka對內存和線程的處理。
測試環境詳情
- 處理器– Intel Core i5-2410M CPU @ 2.30 GHz
- 內存– 4 GB
- 操作系統– Windows 7 Enterprise
- 應用程序服務器– Apache Geronimo v2.2.1
- 編譯器和構建工具– Apache Maven v2.2.1
- Java版本– 1.7.0_03
- Akka版本– Akka 2.0.2
- 數據庫– Apache Derby
我們可以做的其他優化:
- 基于請求模式進行分組的Akka未類型化參與者池。 說一個小池僅滿足不那么頻繁使用的請求,而一個大池(或多個池)滿足更頻繁使用的請求(例如獲取報價或獲取帳戶)。 可以基于請求模式更改池大小的比率,以獲得更好的吞吐量。
- 使用actor的PreStart和PostStart函數為數據庫添加初始化任務,例如獲得連接和關閉連接或任何其他初始化任務。
- Akka無類型演員,用于并發處理持股,同一帳戶和會話的多個報價。
- 使用Akka actor層次結構,以便有多個級別的actor,而更高級別的supervisor actor將一個任務劃分為較小的子任務,并委派給下一級別的子actor。
- 優化actor系統的Akka調度程序線程池大小。
我想對我的同事Chintu Vijay表示感謝,他進行并運行了測試。
參考: Akka Essentials博客上的JCG合作伙伴 Munish K Gupta 向JEE Apps添加了渦輪增壓器 。
翻譯自: https://www.javacodegeeks.com/2013/01/adding-turbochargers-to-jee-apps.html