2009-12-30 49 views
8

這裏是解決在Web應用程序中長時間運行的查詢問題(異步請求)

企業Web應用程序的用戶正在執行導致長(超長)數據庫查詢任務的問題(或其他長期處理密集型任務)

問題:

  • 請求超時 - 經過一段時間的用戶可能會收到一個請求超時
  • 會話超時 - 如果沒有使用會話保持方法,一個SES可發生錫安超時
  • 請求線程鎖
    • 由於請求線程沒有返回,可能會阻止新的requrests(如果達到了池限制)
    • 在某些應用服務器的服務器的健康狀況可能會觸發強制(由於長時間運行的請求的線程)的節點或應用程序的重啓
  • 如果用戶離開頁面:
    • 交易沒有被取消 - 導致無用的處理,沒有人會受益於
    • 用戶不能返回看到的結果,他們完成
  • 沒有取得任何進展跡象之後 - 用戶只需等待頁面刷新

我提出了幾種解決方案,但我不確定哪個更好(在所有方面,性能,最佳實踐,優雅和可維護性),我想知道您推薦的解決方案是什麼,如果存在我錯過了一個解決方案? (可能是肯定的,而且很多)

壞的解決方案:使用請求線程的工作線程,保存在會話進度狀態,有一個AJAX調用另一個相同常要求

檢查狀態(會話)

妥協解決方案:創建您自己的線程池,處理監視線程,工作線程並通過同步分佈式事務性高速緩存或持久性存儲中的狀態來照顧集羣。這會釋放請求,但會創建應用程序服務器不知道的線程,並且不會在取消部署中關閉。它取決於你以一種乾淨的方式關閉線程,並且總是有可能最終泄露一些東西。這也不是J2EE的方式。

的J2EE解決方案:使用JMS的異步任務,這就是它是

春節的解決方案換貨:使用Spring Batch的

你會怎麼做/在你的項目做?還有哪些其他解決方案?我認爲上面哪個是你認爲的贏家?

回答

13

我會做你的所謂的「不好解決」和「J2EE解決方案」的組合:

  1. 原來的UI線程發送異步JMS消息,「後端」,並返回。
  2. 後端接收異步請求並對其進行處理。
  3. 當在後端達到結果(或錯誤)時,它將返回到控制器層。
  4. 仍在進行AJAX輪詢或使用Bayeux/Cometed的用戶界面接收並顯示結果。

訣竅是匹配請求/響應對。我會做這樣的:

  1. 創建「AsyncManagerService」(AMS),有會議,甚至是應用範圍廣,因此所有線程聊到了同一個實例。
  2. AMS擁有一張地圖,其中ID爲關鍵字,任何對象爲值。
  3. 在創建請求JMS消息時,生成一個唯一的隨機密鑰並將其放入消息的jmsCorrelationId以及映射中,並將其作爲值NULL。還要將該ID傳遞給用戶界面。
  4. 只要地圖中的值爲NULL,讓UI線程輪詢AMS與以前生成的ID
  5. 當結果準備就緒時,讓JMS接收器將其放入給定ID的AMS'映射中。
  6. 下一次UI線程輪詢地圖時,它將收到答案並停止輪詢。

這是從任何具體域乾淨和抽象。純技術解決方案。

即使你不喜歡輪詢,HTTP設計也是無狀態的,我認爲這種輪詢方式只能在定義好的時間間隔內進行。

不管怎樣,我實現了一個系統,正是這種模式,它運行得很好......

+0

寫得好的答案,謝謝 – 2009-12-30 14:43:38

+0

@Ehrann:謝謝!實施它,讓我知道你是否有一個更順利的解決方案... – raoulsson 2009-12-30 21:56:09

1

我之前使用的解決方案涉及Jetty Cometd而不是AJAX。Ajax和Cometd之間的主要區別在於Cometd可以使用更多的pub/sub模型 - 客戶端(在這種情況下是web瀏覽器)向發佈者(您的應用程序)提供子鏈接,並且應用程序將更新和通知推送到Web瀏覽器與Web瀏覽器對服務器進行持續輪詢的ajax模型相同。即使您不使用碼頭,您也可以使用Cometd解決方案 - 您可以將碼頭罐放入相應Web服務器的lib文件夾中,您應該很好。

0

這些查詢運行了多久?

如果您正在討論會話過期,那麼最好讓用戶不要等待。對於用戶而言,在查詢的選項卡中等待每隔20分鐘一直很煩人。因此,如果真的很長的查詢是這種情況,或許最好是改變UI方法並讓用戶「訂購」他(她)後來回來查看的查詢,或者甚至在郵件發送時通過郵件通知準備。

在這種情況下,我會在DB中準備好查詢,並在單獨的表中進行緩存。這意味着,我會讓Web服務器一次工作來註冊請求,有一個數據庫任務或一個單獨的進程/服務器根據請求準備查詢並通知用戶,然後讓Web服務器在用戶返回時顯示它們結果。

+0

這是由所有建議的解決方案覆蓋,顯然會有一些後臺服務器進程,並向用戶發送一些通知。問題是什麼特定的技術(Java技術是acurate)是最佳實踐使用 – 2009-12-30 14:41:43

+0

@Ehrann:我建議通知是「離線」,如果它是一個非常長的等待時間,並且我建議它在一個DB作業。 – 2009-12-30 14:48:32

1

顯示一條消息給用戶「您的請求被接受,並會採取一些時間去更新」

您創建一個表來存儲所有這些事務,並在服務器上批量處理這些事務。

用戶不必等待很長時間,他會很高興看到該消息。您的交易處理完成後,您可以發送確認電子郵件。

這是我認爲的最佳解決方案。

相關問題