Javenue logo

Javenue

Программирование на Java

Информационные технологии

Использование Connection Pool в Tomcat - DBCP

[Статья была написана в 2005 году и частично устарела. По возможности будет переписана.]

В наше время трудно представить себе веб-приложение, которое не использовало бы базу данных для своих нужд. При работе с базой данных очень важно следить за соединениями к базе и вовремя освобождать их. Для этих целей разработчики веб-приложений пишут так называемые Connection Pools (или же используют/исправляют существующие).

Одним из лучших сервлет-контейнеров есть Apache Tomcat. Tomcat хорошо еще и тем, что он использует свой собственный DBCP (Database Connection Pool).

О том, как в полной мере воспользоваться преимуществами DBCP сервера Tomcat, и будет эта статья.

Предположим, в сети по IP-адресу 192.168.0.5 находится Oracle с базой данных TESTDB и пользователем DBuser с паролем DBpass.

Для того, чтобы настроить Tomcat на эту базу, необходимо в конфигурационном фале conf\server.xml в раздел Context (если нету, необходимо создать его внутри раздела Host непосредственно перед его окончанием) добавить следующие строки:

<resource name="newDS" auth="Container" 
type="javax.sql.DataSource"/>
<resourceparams name="newDS">
  <parameter>
    <name>factory</name>
    <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  </parameter>
  <parameter>
    <name>url</name>
    <value>jdbc:oracle:thin:@192.168.0.10:1521:TESTDB</value>
  </parameter>
  <parameter>
    <name>username</name>
    <value>DBuser</value>
  </parameter>
  <parameter>
   <name>password</name>
    <value>DBpass</value>
  </parameter>
  <parameter>
     <name>driverClassName</name>
     <value>oracle.jdbc.driver.OracleDriver</value>
  </parameter>
  <parameter>
    <name>maxActive</name>
    <value>100</value>
  </parameter>
  <parameter>
    <name>maxIdle</name>
    <value>10</value>
  </parameter>
  <parameter>
    <name>maxWait</name>
    <value>10000</value>
  </parameter>
  <parameter>
    <name>removeAbandoned</name>
    <value>true</value>
  </parameter>
  <parameter>
    <name>removeAbandonedTimeout</name>
    <value>60</value>
  </parameter>
</resourceparams>

С помощью этой конфигурации создается Data Source с именем newDB. Рассмотрим параметры этого объекта.

Параметр factory говорит о том, какую фабрику нужно использовать для создания объектов, реализующих интерфейс DataSource. Следующий параметр представляет собой URL для доступа к базе данных. Параметры username и password содержат соответсвенно имя пользователя/схемы и пароль. Имя драйвера базы данных указано в параметре driverClassName.

Следующие параметры отвечают непосредственно за Connection Pool. Рассмотрим их немного подробнее.

maxActive - максимальное количество соединений, которые будут содержаться в пуле. Если значение этого параметра установить в 0, то ограничения на кол-во подключений к базе не будет. В конфигурации самого сервера баз даннных такой параметр тоже существует. Думаю не стоит объяснять, почему его значение должно быть больше, чем maxActive.

maxIdle - максимальное количество простаивающих соединений, которые будут оставаться в пуле. При значении этого параметра равным нулю, ограничений не будет.

maxWait - если время ожидания соединения превысит значение параметра maxWait (в миллисекундах), пользователь получит Exception. При значении maxWait равным -1, время ожидания не ограничено.

Прошу обрать ваше внимание на следующую очень важную вещь. Tomcat работает под виртуальной машиной (JVM). Для освобождения памяти JVM использует сборщик мусора (garbage collector). GC имеет очень высокий приоритет и при освобождении памяти Tomcat будет входить в состояние ожидания (на доли секунды, реже - на несколько секунд). При маленьких значениях maxWait, соединение может не установиться из-за таймаута. Значение 10000 в подавляющем большинстве случаев будет оптимальным.

removeAbandoned - при установке этого парамера в true, заброшенные соединения будут освобождены, когда кол-во свободных соединений в пуле невелико.

removeAbandonedTimeout - этот параметр указывает в секундах время, через которое любое простаивающее соединение будет считаться заброшенным.

После этого, нужно настроить наше веб-приложение для работы с DataSource. Делается это так, в файле-дескрипторе web.xml пишем:

<resource -ref>
  <description>Описание ресурса</description>
  <res -ref-name>newDB</res>
  <res -type>javax.sql.DataSource</res>
  <res -auth>Container</res>
</resource>

Наконец-то мы и добрались до использования всего вышенаписанного на практике. Чтобы доступиться до нашего DataSource через JNDI и создавать соединения с базой можно написать такой себе класс (импорт пакетов и обработка ошибок опущены):

public class ConnectionFactory {
  private static final String DATASOURCE_NAME = "newDB";
  private static DataSource ds = null;
	
  static {
    Context initContext = new InitialContext();
    Context envContext = (Context)initContext.lookup("java:/comp/env");
    ds = (DataSource) envContext.lookup(DATASOURCE_NAME);
  }

  public static Connection getConnection() throws SQLException{
    Connection conn = ds.getConnection();
    return conn;
  }
}

Жду ваших комментариев.


Комментариев: 4

  Выйти

  * для публикации комментариев нужно  

Андрей:

Статья замечательная, просто и понятно, но так же как и во всех статья про DBCP не раскрыт термин maxIdle. Мне лично до сих пор не понятно, что такое простаивающие и заброшенные соединения и как Tomcat определяет эти типы соединений.

c0nst:

Заброшенные соединения - это условный термин. Tomcat обозначает соединение как заброшенное по значению параметра removeAbandonedTimeout. Это сделано из тех соображений, что в некоторых ситуациях idle соединения могут возникнут в результате некорректной работы программы (сбоев). Поэтому нужно иметь хоть какую-то возможность отследить это и освободить такого рода connections.

Nitro:

Статья отличная. Кое что добавлю:

Тег позволяет задать режим аутентификации пользователя при попытке установки соединения с БД.

Значение «Container» говорит, что аутентификацию будет выполнять контейнер на основе предоставленных ему идентификатора и пароля (или сертификата) пользователя (например, реквизиты пользователя указывались в дескрипторе для пула соединений с выбранной СУБД). Другое возможное значение – «Application» – говорит о том, что параметры пользователя должны явно указываться на уровне Java-кода при обращении к фабрике соединений с СУБД.

Vermut:

У меня есть некоторые опасения:

1. Tomcat только создает ресурсы с помощью фабрик, в данном случае пул соеденений. Но помоему он не управляет их жизенным циклом, то есть его не интересует их корректное уничтожение. Необходимо в server.xml прописать слушателя жизненного цикла сервера, который закроет пул.

2. Пул прописан в server.xml, а не в контесте приложения, если предполагается расшарить его на несколько приложений, то следует остерегаться:

2.1 Утечки соеденений в одном приложении, выведут из строя, другие приложения использующие этот пул.

2.2 Наверно будет затруднительно определить в каком именно приложении происходят утечки, или вобще сколько конкретное приложение требует соеденений.