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 соединений), но затем им нужно вызвать метод valuStatus, который также пытается получить соединение из пула для своих собственных нужд. Но пул исчерпан, и ни один поток не может освободить соединение, потому что все они ждут оценки Status. Итак, тупик есть. Я пытался разместить тип распространения SUPPORT для valuStatus, но я получаю исключение "соединение в пуле закрыто". Тогда я подумал, что это может сработать, если я переместу вызов valuStatus из convertDocumentToJSON и напишу такой код.

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

но в этом случае я тоже столкнулся с той же ошибкой (исчерпанный пул). Пожалуйста, дайте мне совет, что я должен исправить в своем коде

1 ответ

Вам нужно что-то ограничить использование соединений, попробуйте использовать GPars, например

import groovyx.gpars.GParsPool

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

Существуют XXXXParallel версии обычных методов сбора данных groovy, например collectParallel, с которыми вы можете поиграть, чтобы повысить производительность.

Другие вопросы по тегам