2012-06-01 1 views
1

Моя команда должна внести некоторые изменения и обновить старое веб-приложение. Это приложение имеет один основной поток и от 5 до 15 потоков демона, используемых в качестве рабочих для извлечения и вставки данных в БД.проблемы с объединением пула соединений в многопоточной среде

Всех этих нити имеют такую ​​конструкцию (здесь упрощена для удобства):

public MyDaemon implements Runnable { 

    // initialization and some other stuffs 

    public void run() { 
     ... 
     while(isEnabled) { 
       Engine.doTask1(); 
       Engine.doTask2(); 
       ... 
       Thread.sleep(someTime); 
     } 
    } 
} 

Класс двигателя обеспечивает ряд статических методов, используемых для maipulate других методов классов DataAccessor, некоторые из этих методов были статичными:

Классы DataAccessor обычно взаимодействуют с БД, используя простые операторы JDBC, заключенные в синхронизированные методы (статические для некоторых классов). DataSource настроен на сервере.

public ThatDataAccessor { 

    public synchronized void retrieve(DataType data) { 
     Connection conn = DataSource.getConnection(); 
     // JDBC stuff 
     conn.close(); 
    } 
    ... 
} 

проблема является то, что основной поток должен подключиться к БД, и когда эти потоки демона работают легко запускать из доступных соединений из пула, получая «ожидание подключения тайм-аута» исключения. Кроме того, иногда даже те потоки демона получают одно и то же исключение.

Мы должны избавиться от этой проблемы.

У нас есть пул соединений, настроенный на 20 соединений, и больше не может быть добавлено, так как это «20» - это стандарт нашей производственной среды. Некоторые блоки кода необходимо синхронизировать, даже если мы планируем переместить «синхронизированное» ключевое слово только там, где это действительно необходимо. Но я не думаю, что это действительно изменило бы ситуацию.

Мы не испытываем многопоточности программирования, и мы никогда раньше не сталкивались с этой проблемой объединения пулов, поэтому я спрашиваю: - проблема из-за дизайна этих потоков? Есть ли недостатки, которых мы не заметили?

У меня есть профилированные классы потоков один за другим, и пока они не работают параллельно, кажется, что нет «узкого места», чтобы оправдать «ожидающий время ожидания соединения». Приложение работает на WebSphere 7, используя Oracle 11g.

ответ

1

Вероятно, у вас, вероятно, отсутствует блок где-то, чтобы вернуть соединения обратно в пул. С hibernate, я думаю, что это, вероятно, сделано, когда вы вызываете close() или, возможно, для транзакций, когда вы вызываете rollback(). Но я все равно позвоню.

Например, я написал быстрый и грязный бассейн сам продлить старое приложение, чтобы сделать это многопоточный, и вот некоторые из кода обработки (который должен быть бессмысленным для вас, кроме finnally блока):

try { 
    connection = pool.getInstance(); 
    connection.beginTransaction(); 
    processFile(connection, ...); 
    connection.endTransaction(); 
    logger_multiThreaded.info("Done processing file: " + ...); 
} catch (IOException e) { 
    logger_multiThreaded.severe("Failed to process file: " + ...); 
    e.printStackTrace(); 
} finally { 
    if (connection != null) { 
     pool.releaseInstance(connection); 
    } 
} 

Общепринято, что люди не могут правильно использовать блоки блоков ... Например, посмотрите учебник hibernate this и перейдите к самому нижнему примеру. Вы увидите, что в try {} он использует tx.commit(), а в catch {} он использует tx.rollback(), но у него нет session.close(), и, наконец, нет. Поэтому, даже если он добавил «session.close()» в try и catch, если его блок try бросил что-то другое, кроме RuntimeException, или его catch вызвал дополнительное исключение перед попыткой или исключение без HibernateException перед откатом() , его связь не будет закрыта. И без session.close(), я не думаю, что это действительно очень хороший код. Но даже если код работает, наконец, дает вам уверенность в том, что вы защищены от этого типа проблем.

Поэтому я бы переписал его методы, которые используют сеанс, чтобы соответствовать идиоме, указанной на странице документации hibernate this. (а также я не рекомендую его бросать RuntimeException, но это другая тема).

Так что если вы используете Hibernate, я думаю, что вышеописанное достаточно. Но в противном случае вам нужно быть более конкретным, если вам нужна специальная помощь по коду, но в противном случае достаточно простой идеи, что вы должны использовать, наконец, чтобы закрыть соединение.

+0

Я использую простой JDBC, но я чувствую, что проблема аналогична той, которую вы выставили. Некоторые части кода очень запутаны, многие команды и разработчики работали над этим, и в некоторых случаях мы обнаружили капли запутанных и вложенных блоков try-catch ... Мы отправимся на поиски этих незакрытых соединений, надеясь, что это решит проблему проблема. :) – javatutorial

 Смежные вопросы

  • Нет связанных вопросов^_^