簡體   English   中英

EJB如何並行化長時間CPU密集型流程?

[英]How can an EJB parallelize a long, CPU intensive process?

該應用程序具有CPU密集型長進程,當客戶端請求時,該進程當前在一個服務器(EJB方法)上串行運行。

理論上可以(從概念的角度)將該進程拆分為N個塊並並行執行它們,只要可以收集並連接所有並行作業的輸出,然后再將其發送回發起進程的客戶端。 我想使用這種並行化來優化性能。

如何使用EJB實現此並行化? 我知道我們不應該在EJB方法中創建線程。 相反,我們應該發布消息驅動bean(MDB)消息(每個作業一個)。 但那時它不再是同步通話了。 在這種情況下,同步似乎是一個要求,因為我需要在將所有作業的輸出發送回客戶端之前收集它們的輸出。

這有解決方案嗎?

有各種各樣的方法可以做到這一點。

一,您可以使用EJB Timer創建一個立即啟動的一次運行進程。 這是在后台生成進程的好方法。 EJB Timer與特定的Session Bean實現相關聯。 您可以將EJB計時器添加到您希望能夠執行此操作的每個會話Bean,也可以使用單個會話Bean,然后可以通過某種調度機制調用應用程序邏輯。

對我來說,我傳遞了一個可序列化的blob參數以及一個符合特定接口的類名,然后執行該類的通用會話Bean。 通過這種方式,我可以輕松地背景大部

關於EJB Timer的一個警告是EJB Timers是持久的。 創建EJB計時器后,它將保留在容器中,直到其作業完成或取消。 問題在於如果你有一個長時間運行的進程,並且服務器出現故障,當它重新啟動時,進程將繼續並重新啟動。 請注意,這可能是一件好事,但前提是您的流程已准備好重新啟動。 但是如果你有一個簡單的過程迭代“10,000項”,如果服務器在第9,999項下降,當它恢復時,你可以很容易地看到它只是從第1項開始。這一切都是可行的,只是需要注意的警告的。

另一種背景的方法是你可以使用JMS隊列。 在隊列上放置一條消息,處理程序從應用程序的其余部分運行。

這里聰明的部分,以及我利用Timer Bean的工作做的事情,你可以根據你配置系統的MDB實例數來控制運行多少“作業”。

因此,對於以多個並行塊運行進程的特定任務,我執行任務,將其分解為“片段”,然后在消息隊列中發送每個片段,MDB在其中執行它們。 如果我允許10個MDB實例,我可以同時運行任何任務的10個“部分”。

這實際上運作得非常好。 將進程分解並通過JMS隊列進行路由會產生一些開銷,但這基本上都是“啟動時間”。 一旦它開始,你將獲得真正的好處。

使用Message Queue的另一個好處是,您可以在單獨的計算機上執行實際長時間運行的進程,或者您可以輕松創建一組計算機來處理這些進程。 然而,界面是相同的,代碼不知道差異。

我發現,一旦你將一個長時間運行的流程降級到后台,你就可以為那個流程的即時訪問權限付出代價。 也就是說,沒有理由直接監視執行類本身,只是讓它們向數據庫,JMX或其他任何東西發布有趣的信息和統計信息,而不是直接監視對象,因為它共享相同的內存空間。

我很容易設置一個框架,允許任務在EJB Timer或MDB分散隊列上運行,任務是相同的,我可以監視他們的進度,停止它們等等。

您可以組合分散技術來創建多個EJB Timer作業。 MDB的一個免費優勢是它充當線程池,可以限制您的工作(因此您不會因為太多的后台進程而突然使您的系統飽和)。 只需通過利用容器中的EJB管理功能,您就可以“免費”獲得此功能。

最后,Java EE 6為Session Bean方法提供了一個新的“異步”(或某種)限定符。 我不知道它是如何工作的細節,因為我還沒有使用新的Java EE 6容器。 但我想你可能不會想要為這個設施更換容器。

這個特殊問題已經出現過多次,我將總結出幾種可能的解決方案,其中只有一種我會推薦。

使用commonj API中的WorkManager。 它允許Java EE容器中的托管線程,並且專門設計用於適合您的用例。 如果您使用的是WebSphere或WebLogic,則這些API已在您的服務器中可用。 對於其他人,您必須自己提供第三方解決方案。

WorkManager信息

相關問題為什么不鼓勵產生線程

EJB最終是提供請求/回復語義的客戶端 - 服務器系統的事務組件。 如果您發現自己需要在請求/回復周期的范圍內對長時間運行的事務進行歸檔,那么您的系統架構師(某處)就會出錯。

您描述的情況由具有消息傳遞后端的基於事件的體系結構干凈且正確地處理。 初始事件啟動進程(然后通過讓工作者訂閱事件主題可以簡單地並行化)並且聚合進程本身在完成時引發事件。 您仍然可以在請求/回復周期的范圍內擠壓這些序列,但您必然會違反Java EE系統架構規范的字母和精神。

回到未來 - Java EE 7通過ManagedThreadFactory,ManagedExecutor服務等(JSR 236:Java EE的並發實用程序)提供了更多的並發支持,您可以使用它來創建自己的“托管”線程。它不再是EE AS中的禁忌通過使用ManagedThread * API來支持它(Wildfly?)

更多細節

https://jcp.org/aboutJava/communityprocess/ec-public/materials/2013-01-1516/JSR236-EC-F2F-Jan2013.pdf http://docs.oracle.com/javaee/7/tutorial/doc /concurrency-utilities002.htm

我曾經參與過EJB事務一次最多運行5個小時的項目。 AARGH!

同樣的應用程序還有一位BEA專家顧問,他們批准他們從交易中啟動了額外的線程。 雖然它在規格和其他地方被推薦,但它並不會自動導致失敗。 你需要知道你的額外線程是在容器的控制之外,因此如果出現問題,那就是你的錯。 但是如果你能確保在最壞的情況下啟動的線程數不超過合理的限制,並且它們都在合理的時間內干凈地終止,那么很可能像這樣工作。 事實上,在你的情況下,它聽起來幾乎是唯一的解決方案。

有一些稍微深奧的解決方案可能會讓您的EJB應用程序到達服務的另一個應用程序,然后在返回EJB調用者之前執行多線程處理。 但這基本上只是改變了問題。

但是,您可以考慮使用線程池解決方案來保持生成的線程數的上限。 如果你有太多的線程,你的應用程序將表現得非常糟糕。

你已經很好地分析了這種情況,不,沒有與EJB模型相匹配的模式。

主要禁止創建線程,因為它繞過了應用程序。 服務器線程管理策略也因為事務

我參與了一個有類似需求的項目,我決定產生額外的線程 (然后反對sepc)。 並行化的操作是只讀的,因此它對事務有效(線程基本上沒有與它們相關的事務)。 我也知道每次EJB調用都不會產生太多線程,因此線程數不是問題。 但是如果您的線程應該修改數據,那么您就會嚴重破壞EJB的事務模型。 但如果你在純計算中操作,那可能沒問題。

希望能幫助到你...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM