2017-05-29 76 views
2

爲了使用多線程返工一個服務方法後,我發現,如果多個用戶試圖請求頁面(和調用服務方法)很多次,服務器開始拋出「不能得到連接池已用盡「異常。讓我舉一個我的服務班的例子。Grails。不能得到一個連接,池耗盡

class DocumentService { 
    def convertToJSON() { 
     docs.collect { doc -> 
     taskExecutor.submit({ 
      Document.withNewSession { 
       def json = convertDocumentToJSON(doc) 
      } 
     } as Callable) 
     }.collect { it.get() } 
    } 

    def convertDocumentToJSON(doc){ 
     def json = [:] 
     // ... fill json with data using doc and GORM requests 
     evaluateStatus(json) 
     return json 
    } 

    def evaluateStatus(json){ 
     //... some work using database through GORM 
    } 
} 

我一直在努力解決這個問題超過一週,我找不到解決方案。我不太清楚Grails是如何處理會話,連接和事務的。我的猜測是跟隨。當convertDocumentToJSON被調用時,它需要從連接池(4個用戶,每個用戶25個線程= 100個連接),但這時就需要調用evaluateStatus方法,該方法還嘗試獲取從池中它自己的需要連接。但池已經耗盡,沒有一個線程可以釋放連接,因爲它們都在等待evaluateStatus。所以,存在僵局。我試圖爲evaluateStatus放置SUPPORT傳播類型,但我得到「池連接已關閉」異常。後來我想,如果我擺脫convertDocumentToJSON evaluateStatus調用它可能工作,並寫了這樣的代碼

def convertToJSON(){ 
    docs.collect { doc -> 
    taskExecutor.submit({ 
     Document.withNewSession { 
      def json = convertDocumentToJSON(doc) 
      evaluateStatus(json) // move call from convertDocumentToJSON 
     } 
     } as Callable) 
    }.collect { it.get() } 
} 

但在這種情況下,我也面臨着同樣的錯誤(用盡池)。請給我建議我應該在我的代碼修復

回答

0

你需要的東西扼殺連接的使用,請嘗試使用GPars例如

import groovyx.gpars.GParsPool 

GParsPool.withPool() { 
    docs.collect { 
     // do your stuff... 
    } 
} 

有通常的groovy收集方法的XXXXParallel版本,例如, collectParallel,您可以隨身攜帶以協助演奏。

+0

謝謝。是的,我嘗試使用GPars,但它僅適用於ForkJoinPool。我實際上並不記得是什麼問題,但它不符合我的期望。我真的很好奇 – volea

+0

以上的代碼有什麼問題taskExecutor是一個Java ExecutorService嗎?如果有的話,它創建的游泳池有多大? –

+0

是的,它是ExecutorService。池大小爲30.連接池 - 100 – volea