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

В общих чертах что такое пул.
Пул (pool) - это такой "бассейн" или "резервуар" из которого можно брать "живые" объекты для дальнейшего их использования.
В данной статье будут рассматриваться только пулы подключений к БД, но в жизни программиста могут повстречаться пулы разных объектов, например многим знаком Thread Pool.
В общем случае, пул "каких-то объектов" - это шаблонный способ решения проблемы хранения и раздачи объектов (и самое главное поддержания их в нормально рабочем состоянии).

По аналогии с бассейном, в нормальных пулах постоянно протекают некоторые процессы. Например осуществляется проверка не "протухли" ли объекты. Нужно ли создать новые? Сколько времени объекты находятся в пуле? Во многих пулах есть своя "ватерлиния" (high water mark), которая указывает на максимальный "объем" пула.

В этой статье будет кратко описан JDBC Connection Pool.

Использование такого пула оправдано тем, что каждое подключение к БД это ресурсоёмкая операция. Поэтому более экономная стратегия это установить несколько подключений и следить за их состояниям, по мере необходимости добавлять новые.

Существует несколько реализаций пулов подключений к БД.

Можно даже сделать свою имплементацию. Это не сверхзадача. Опасность заключается в том, что если сделать чуть-чуть не аккуратно, то ваш бассейн начнет протекать или объекты будут "тухнуть".
Для серверного ПО это особо не приятно.
Тем не менее, в 90-ые годы многие java программисты писали свои connection pool.

Сейчас конечно можно взять готовый.

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

  • У вас нормальный Application Server. В этом случае у вас готовый, надежный промышленный пул "из коробки".
  • Вы используете СУБД Oracle. У вас реализация пула "из коробки" - в jar-ике с драйверами.

В обоих случаях, самое главное научиться всё правильно настраивать.

Если вы не можете себе позволить нормальный сервер (или оракл), то можно попробовать разобраться с решениям "для бедных".

Итак варианты:

DBCP

DataBase Connection Pool - этот пул очень долгое время приводится в примерах на сайте Apache Tomcat.
Это не самый лучший пул, т.к. может создать deadlock-и. На данный момент я бы не стал его рекомендовать для применения в реальных (продакшн) версиях.

C3P0


Название этого пула созвучно с именем робота золотистого цвета из звездных войн (в фильме этого робота создал молодой Дарт Вейдер, он же Анакин Скайоукер).
Краткое объяснение этому названию следующее: Connection Pool 3.0 -> СP30 -> C3P0. Подробности можно прочитать по ссылке.

Это действительно неплохой пул. Например, в какой-то момент создатели одного известного ORM-фреймворка стали приводить в своих примерах именно работу с с3p0 (и ругаться на dpcp).

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

Можно скачать с сайта (ссылка) или установить из maven-репозитория (groupId:c3p0, artifactId:c3p0).

Принцип настройки JNDI ресурсов в томкате думаю объяснять не нужно. Всё просто. Можно указать как глобальные ресурсы, а в веб-приложении указать ссылку, либо можно указать непосредственно в context.xml. Все зависит от того, где у вас хранятся библиотеки и какая у вас конфигурация сервера.

Пример настройки (MySQL):

    <resource auth="Container" 
        description="DB Connection" 
        driverClass="com.mysql.jdbc.Driver" 
        user="user" 
        password="password"
        jdbcUrl="jdbc:mysql://localhost:3306/databasename?useUnicode=yes&amp;characterEncoding=UTF-8" 
        factory="org.apache.naming.factory.BeanFactory" 
        type="com.mchange.v2.c3p0.ComboPooledDataSource" 
        name="jdbc/db" 
        maxPoolSize="10" 
        minPoolSize="0" 
        maxConnectionAge="100"
        acquireRetryAttempts="60"
        acquireIncrement="1" 
        preferredTestQuery="SELECT 1"
        testConnectionOnCheckout="true"></resource>

Важно! Установить пул особого ума не требует. Основная задача настроить так, чтобы он стабильно работал и выдерживал нагрузку.
Значение каждого параметры нужно прочитать в документации.

Некоторые важные детали:

  • Может оказаться, что JDBC URL есть амперсанд (&). Если настройка осуществляется через XML-файл, то & надо заквотить (вместо param1=value1¶m2=value2, пишем param1=value1&amp;param2=value2).
  • preferredTestQuery - запрос который проверяет подключение к БД. Зависит от конкретной СУБД.
  • testConnectionOnCheckout - прожорлив, если можно то лучше не использовать.
  • maxPoolSize и minPoolSize - возможные максимальное и минимальное количество подключений в пуле.
  • acquireRetryAttempts - если СУБД не доступна, сколько раз пытаться подключится. Ставим в 0 если хотим, чтобы долбились до бесконечности.

Tomcat 7 JDBC Pool


В 7-ом Tomcat выпустили свой собственный пул. Подробнее можно прочитать на сайте.

    <resource name="jdbc/db"
        auth="Container" 
        description="DB Connection" 
        username="username" 
        password="password"
        driverClassName="com.mysql.jdbc.Driver" 
        url="jdbc:mysql://localhost:3306/databasename?useUnicode=yes&amp;characterEncoding=UTF-8" 
        maxActive="10" 
        maxIdle="3" 
        maxWait="100"
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
        type="javax.sql.DataSource"></resource>

Некоторые важные детали:

  • Нужно быть внимательным с атрибутами. Например в с3p0 был атрибут user, здесь - username (driverClass - driverClassName, jdbcUrl - url). Поскольку реализация разная, поэтому и настройки отличаются!
  • Можно использовать и не в семерке. Из дополнительных зависимостей - tomcat-juli.jar.

Про Oracle


C Oracle все не просто. Как правило, Oracle используют серьезные организации, у которых должен быть штатный ДБА-шник. Самое правильное и разумное решение, чтобы тюнинг пула подключений к СУБД осуществлялся вместе с администратором баз данных.
Если у вас Oracle XE (бесплатная), то у вас может быть целый букет разного рода ошибок и сложностей связанных с локалью и настройкой.
Поскольку эта статья не про то, как настроить Oracle XE, а про пулы подключений, поэтому приведу примерную конфигурацию, которую использую для девелоперских целей.

     <resource auth="Container" 
         factory="oracle.jdbc.pool.OracleDataSourceFactory" 
	 type="oracle.jdbc.pool.OracleDataSource" 	
	 name="jdbc/db"
	 user="scott"
	 password="tiger" 
	 connectionCachingEnabled="true"
	 url="jdbc:oracle:thin:@localhost:1521:XE"></resource>
  • Важно! Это только для разработки. В продакшн такую настройку использовать не стоит. Проконсультируйтесь с вашим DBA! Это не шутка.
  • Еще раз внимательно с атрибутами. Отличаются от с3p0 и tomcat 7 jdbc pool
  • Это пример для Oracle 10-ка XE. Для других версий нужно читать документацию, но принцип тот же. Если собираетесь использовать нагугленные из интернета примеры, то обратите внимание на аттрибут factory. В интернете очень много ложных примеров.