Как правильно обрабатывать соединения JDBC с помощью Spring и DBCP? - PullRequest
7 голосов
/ 19 августа 2010

Я использую Spring MVC для создания тонкого слоя поверх базы данных SQL Server.Когда я начал тестирование, кажется, что он не очень хорошо справляется со стрессом :).Я использую Apache Commons DBCP для обработки пула соединений и источника данных.

Когда я впервые попробовал ~ 10-15 одновременных подключений, он зависал, и мне приходилось перезагружать сервер (для разработчика я использую Tomcat, но в конечном итоге мне придется развернуться на Weblogic).

Вот мои определения бинов Spring:

<bean id="dataSource" destroy-method="close"
      class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="[...]"/>
    <property name="username" value="[...]" />
    <property name="password" value="[...]" />
</bean>

<bean id="partnerDAO" class="com.hp.gpl.JdbcPartnerDAO">
    <constructor-arg ref="dataSource"/>
</bean>

<!-- + other beans -->

И вот как я их использую:

// in the DAO
public JdbcPartnerDAO(DataSource dataSource) {
    jdbcTemplate = new JdbcTemplate(dataSource);
}

// in the controller
@Autowired
private PartnerDAO partnerDAO;

// in the controller method
Collection<Partner> partners = partnerDAO.getPartners(...);

Прочитав немного, я нашелсвойства maxWait, maxActive и maxIdle для BasicDataSource (из GenericObjectPool ).Здесь возникает проблема.Я не уверен, как я должен установить их, с точки зрения производительности.Из того, что я знаю, Spring должен управлять моими соединениями, поэтому мне не нужно беспокоиться об их освобождении.

<bean id="dataSource" destroy-method="close"
      class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="[...]"/>
    <property name="username" value="[...]" />
    <property name="password" value="[...]" />
    <property name="maxWait" value="30" />
    <property name="maxIdle" value="-1" />
    <property name="maxActive" value="-1" />
</bean>

Сначала я установил maxWait, чтобы он не зависал, а вместо этого выбрасывал исключение, когда из пула не было доступного соединения.Сообщение об исключении было:

Не удалось получить соединение JDBC;Вложенное исключение - org.apache.commons.dbcp.SQLNestedException: не удается получить соединение, ошибка пула Тайм-аут ожидания незанятого объекта

Есть несколько длительных запросов, но исключение было выдано независимо отсложность запроса.

Затем я установил maxActive и maxIdle, чтобы он не выдавал исключения в первую очередь.Значения по умолчанию 8 для maxActive и maxIdle (я не понимаю, почему);если я установлю их в -1, больше не будет выдаваться исключений, и все кажется работает нормально.

Учитывая, что это приложение должно поддерживать большое количество одновременных запросов, можно ли оставить этинастройки до бесконечности?Будет ли Spring фактически управлять моими соединениями, учитывая ошибки, которые я получал?Должен ли я переключиться на C3P0 , учитывая, что он вроде мертв?

Ответы [ 3 ]

9 голосов
/ 24 июля 2012
Параметр

DBCP maxWait должен быть определен в миллисекундах.30 мс очень низкое значение, попробуйте увеличить его до 30000 мс и попробуйте снова.

6 голосов
/ 20 августа 2010

Как вы уже узнали, пул соединений dbcp по умолчанию - 8 соединений, поэтому, если вы хотите выполнить 9 одновременных запросов, один из них будет заблокирован. Я предлагаю вам подключиться к вашей базе данных и запустить exec sp_who2, которая покажет вам, что подключено и активно, а также заблокированы ли какие-либо запросы. Затем вы можете подтвердить, есть ли проблема в БД или в вашем коде.

Пока вы используете семейство объектов Spring JdbcTemplate, ваши соединения будут управляться так, как вы ожидаете, и если вы хотите использовать необработанный источник данных, убедитесь, что вы используете DataSourceUtils для получения соединения.

Еще одно предложение - до Spring 3, никогда не используя JdbcTemplate, придерживайтесь SimpleJdbcTemplate, вы все равно можете получить доступ к тем же методам, используя SimpleJdbcTemplate.getJdbcOperations () , но вы должны много писать лучший код с использованием обобщений и избавляет от необходимости когда-либо создавать экземпляры JdbcTemplate / NamedParameterJdbcTemplate.

2 голосов
/ 20 августа 2010

Давайте изменим перспективу.

но исключение было брошено независимо от сложности запроса

Это может быть связано с тем, что таблица или записи в таблице, к которой вы запрашиваете, заблокирована (какой-либо другой активной транзакцией) и, следовательно, истекло время ожидания.

Попробуйте выполнить тот же запрос из клиента SQLServer, и, если это займет много времени, вы можете быть уверены, что это является причиной блокировки таблицы или записи.

...