2013-06-29 130 views
0

我有一個運行在Tomcat 7上的Spring 3.0 WebMVC應用程序。在應用程序啓動時,我啓動後臺線程以從數據庫加載內存緩存。該線程通常需要花費一個多小時才能從數據庫加載所有數據。在同一個應用程序中,我有一個@Controller註釋類,它公開了一個REST接口,通過這個接口,客戶端可以從加載的緩存中獲取對象。長時間運行的後臺線程導致HTTP請求超時

我們的一個要求是,在數據加載完成之前完成的任何REST請求都會立即返回一個SERVICE_UNAVAILABLE(503)HTTP代碼給客戶端。爲了做到這一點,我設置了一個布爾標誌的簡單檢查,即在執行任何工作之前,控制器中的每個請求方法都會進行檢查。如果該值爲false,則該方法應該立即以503代碼返回。加載器線程在完成加載後將該標誌設置爲true,以允許請求方法正常工作。

問題是後臺線程似乎導致發送到我的控制器的所有HTTP請求在30秒後超時而不是立即觸發標記並立即向客戶端返回503代碼。我不是Tomcat線程問題的專家,我不知道在創建我的長時間運行的後臺線程時是否做錯了什麼?我基本上使用「implements Runnable」方法創建線程,如this問題中所述,並在包含bean初始化時啓動線程。有沒有更好的方法來啓動Tomcat中長時間運行的後臺線程,而不會干擾請求處理?還是還有別的東西我失蹤了?

+0

你如何同步訪問布爾標誌? –

+0

@DavidSchwartz該標誌是請求方法通過緩存DAO對象檢查的內存緩存中的值。加載器線程在通過相同的高速緩存DAO對象完成時簡單地更新此緩存值,我相信這是線程安全的(不是100%確定);它不會在加載完成之前訪問它,所以我不認爲這是一個問題? – Tom

+0

而不是污染每一項服務,只是實現一個過濾器會不會更容易和更好維護?當然,這並不能解決您所問的問題,但可能會將問題簡化爲單一交互場所。 –

回答

0

如果我是你,我會做不同的幾件事情:

  1. 見,如果你想使用一個外部高速緩存。在過去,我使用Project Voldemort(http://www.project-voldemort.com/voldemort/)取得了一些成功,還有其他的選擇。
  2. 如果您將緩存外部化,那麼重新啓動Tomcat將不需要重新加載緩存。
  3. 構建一個單獨的應用程序,其任務是加載緩存。
  4. 如果您想要處理請求,如果您正在查找的條目在緩存中不可用,請直接從數據庫中查找。
  5. 請勿在Tomcat等應用程序容器中使用自己的線程。 Tomcat內置了自己的線程管理邏輯,創建用戶線程是一個BIG-NO。
+0

我很好奇,如果你有一個參考文件來備份你在#5中的聲明...那個用戶線程不是一個在Tomcat中運行的web應用程序內創建的好主意嗎? – Tom

+0

我記得我讀過羅德約翰遜的書,不幸的是我無法追查它。另外,我在實際上已經看到我們的項目中線程作爲請求處理的一部分開始,導致系統停止生產。我發現這個鏈接在這個主題討論的地方:http://stackoverflow.com/questions/533783/why-spawning-threads-in-java-ee-container-is-discouraged –