Я использую Spring MVC для создания тонкого слоя поверх базы данных SQL Server. Когда я начал тестирование, кажется, что он не очень хорошо справляется со стрессом :). Я использую Apache Commons DBCP для обработки пула соединений и источника данных.
Когда я впервые попробовал ~ 10-15 одновременных подключений, он зависал, и мне приходилось перезагружать сервер (для разработчика я использую Tomcat, но в конечном итоге мне придется развернуться на Weblogic).
Это мои определения bean-компонентов Spring:
И вот как я их использую:
// in the DAO
public JdbcPartnerDAO(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
// in the controller
@Autowired
private PartnerDAO partnerDAO;
// in the controller method
Collection partners = partnerDAO.getPartners(...);
Прочитав немного, я нашел maxWait
, Свойства maxActive
и maxIdle
для BasicDataSource (из GenericObjectPool ). Здесь возникает проблема. Я не уверен, как я должен установить их, с точки зрения производительности. Насколько я знаю, Spring должен управлять моими соединениями, поэтому мне не нужно беспокоиться об их освобождении.
Во-первых, я установил maxWait
, чтобы он не зависал, а вместо этого выбрасывал исключение, когда в пуле не было доступного соединения. Сообщение об исключении было:
Не удалось получить соединение JDBC; Вложенное исключение - org.apache.commons.dbcp.SQLNestedException: не удается получить соединение, ошибка пула Тайм-аут ожидания незанятого объекта
Есть несколько длительных запросов, но исключение было выдано независимо от сложности запроса.
Затем, Я установил maxActive и maxIdle, чтобы он не выдавал исключения в первую очередь. Значения по умолчанию: 8 для maxActive
и maxIdle
(я не понимаю, почему); если я установлю их в -1, больше не будет выдаваться исключений, и все , похоже, будет работать нормально.
Учитывая, что это приложение должно поддерживать большое количество одновременных запросов, можно ли оставить эти настройки бесконечными ? Будет ли Spring фактически управлять моими соединениями, учитывая ошибки, которые я получал? Должен ли я переключиться на C3P0 , учитывая, что он вроде мертв?
Как вы уже выяснили, пул соединений dbcp по умолчанию составляет 8 соединений, поэтому если вы хотите выполнить 9 одновременных запросов, один из них будет заблокирован. Я предлагаю вам подключиться к вашей базе данных и выполнить exec sp_who2
, который покажет вам, что подключено и активно, и блокируются ли какие-либо запросы. После этого вы сможете определить, где проблема - в базе данных или в вашем коде.
Пока вы используете семейство объектов Spring JdbcTemplate, ваши соединения будут управляться так, как вы ожидаете, и если вы хотите использовать необработанный источник данных, убедитесь, что вы используете DataSourceUtils для получения соединения.
Еще одно предложение - до Spring 3 никогда не используйте JdbcTemplate, придерживайтесь SimpleJdbcTemplate, вы все еще можете получить доступ к тем же методам, используя SimpleJdbcTemplate.getJdbcOperations(), но вы обнаружите, что пишете гораздо более приятный код, используя generics, и устраните необходимость создавать экземпляры JdbcTemplate/NamedParameterJdbcTemplate.
Давайте изменим перспективу.
но исключение было выброшено независимо от сложности запроса
Это может быть связано с тем, что таблица или записи в таблице, к которой вы выполняете запрос, были заблокированы (другой активной транзакцией), и поэтому он затягивается.
Попробуйте выполнить тот же запрос с SQLServer Client, и если это займет много времени, то вы можете быть уверены, что причиной является блокировка таблицы или записи.