Что такое пул соединений

Понимание пула соединений

1. Введение

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

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

2. Реализация пула соединений в Tomcat

Чтобы использовать пул соединений Apache Commons DBCP

Чтобы использовать Tomcat JDBC Connection pool

фабрика обязательна, а тип всегда должен быть javax.sql.DataSource

Прелесть DBCP в том, что он может использоваться с таким количеством приложений или сред и работает практически со всеми базами данных на рынке.

3. Сравнение механизмов объединения

В любом случае соответствующие JAR-файлы ( commons-dbcp.jar или tomcat-jdbc.jar ) должны быть включены в путь сборки.

В более старых версиях Apache Commons DBCP (то есть версии 1.2) возникали некоторые неприятные проблемы с безопасностью потоков в условиях высокой нагрузки, что делало его непригодным для такого использования, поэтому пул соединений JDBC Tomcat был переписан.

Источник

Пул подключений PoolConnection

Для разработки приложения можно использовать пулы различного типа объектов, например пул потоков Thread Pool. В данной статье рассматривается только пул подключений Connection Pool к БД.

На сегодняшний день существуют готовые решения. Самое главное научиться их правильно настраивать.

Популярный контейнер сервлетов Apache Tomcat предоставляет собственное решение для создания dbcp, основанное на библиотеке apache-commons-dbcp.

apache dbcp предполагает, что имеется некоторый набор («пул») соединений к базе данных. Когда новый пользователь запрашивает доступ к БД, ему выдаётся уже открытое соединение из этого пула. Если все открытые соединения уже заняты, создаётся новое. Как только пользователь освобождает одно из уже существующих соединений, оно становится доступно для других пользователей. Если соединение долго не используется, оно закрывается.

Чтобы реализовать поддержку пула подключений нужно пройти несколько этапов.

На первом этапе необходимо объявить ресурс (базу данных) в контексте приложения. Ресурс описывается следующим кодом (пример для MySQL) :

Контекст приложения представляет файл XML. Желательно хранить его в %document_root%/META-INF/context.xml, однако это не единственный вариант. Про контекст можно почитать на официальном сайте Tomcat’a: The Context Container.

Далее следует добавить ссылку на этот ресурс в дескрипторе приложения web.xml :

После этого можно использовать пул подключений (connection pool java) в приложении. Для этого следует получить объект Connection в следующем коде :

Для получения источника данных (DataSource) используется механизм JNDI (подробнее про него можно почитать здесь)

Перед возвратом соединения в пул все Statement и ResultSet, полученные с помощью этого соединения, автоматически закрываются в соответствии с API.

Connection Pool C3P0

Пул подключений C3P0 представлен файлом c3p0-0.9.1.2.jar (версия может отличаться). Аббревиатура расшифровывается следующим образом : Connection Pool 3.0 => СP30 => C3P0.

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

Пример настройки C3P0 с БД MySQL :

Теперь установить пул подключений не требует особого ума. Основная задача заключается в настройке его работы, чтобы он стабильно функционировал и выдерживал нагрузку. Дополнительно о значении каждого параметры можно прочитать в документации :

Может оказаться, что jdbc Url включает символ амперсанда ‘&’. Если настройка осуществляется через XML-файл, то надо вместо param1=value1&param2=value2 использовать param1=value1&param2=value2.

Задача создания пула подключений к Oracle не тривиальна. Документация приведена здесь

Пул подключений на уровне java приложения, ComboPooledDataSource

Пул подключений C3P0 можно подключать не только на уровне контейнера приложений Tomcat, но и на уровне самого приложения. Для этого не требуется создавать никаких дополнительных внешних XML файлов, о которых было сказано выше.

Следующий код демонстрирует процесс создания и инициализации пула подключений :

Следующий код демонстрирует как получить Connection из пула, и как его закрыть (вернуть в пул):

Источник

HikariCP — самый быстрый пул соединений на java

Java недавно стукнуло 20 лет. Казалось бы, на сегодняшний день на java написано все. Любая идея, любой проект, любой инструмент на java? — это уже есть. Тем более когда речь идет о таких банальных вещах как пул соединений к базе данных, который используют миллионы разработчиков по всему миру. Но не тут то было! Встречайте — проект HikariCP — самый быстрый на сегодняшний день пул соединений на java.

HikariCP — еще один яркий пример того, что всегда стоить брать под сомнение эффективность некоторых решений, даже если их используют миллионы людей и живут они десятки лет. Хикари — прекрасный пример того, как микро оптимизации, которые по отдельности никогда не смогут дать вам больше 0.00001% прироста — в совокупности позволяют создать очень быстрый и эффективный инструмент.

Этот пост — вольный и частичный перевод статьи Down the Rabbit Hole от автора HikariCP перемешанный с потоком моего сознания.

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

Down the Rabbit Hole

Эта статья — рецепт нашего секретного соуса. Когда Вы начинаете просматривать разного рода бенчмарки, у Вас, как у нормального человека, должна возникнуть к ним здравая доля скептицизма. Когда Вы думаете о производительности и пуле соединений, трудно избежать коварной мысли о том, что пул — самая важная ее часть. На самом деле, это не совсем так. Количество вызовов getConnection() в сравнении с другими операциями типичного JDBC довольно мало. Огромное число улучшений производительности достигается за счет оптимизации враперов вокруг Connection, Statement, и тд.

Для того чтобы сделать HikariCP быстрым (каким он и является), нам пришлось копнуть до уровня байткода и ниже. Мы использовали все известные нам трюки чтобы JIT помог Вам. Мы изучали скомпилированный байткод для каждого метода и даже изменяли методы так, чтобы они попадали под лимит инлайнинга. Мы уменьшали количество уровней наследования, ограничивали доступ к некоторым переменным, чтобы уменьшить область их видимости и удаляли любые приведения типов.
Иногда, видя что метод превышает лимит инлайнинга, мы думали о том как изменить его таким образом, чтобы избавится от нескольких байт-инструкций. Например:

Достаточно простой метод, который проверяет, есть ли ошибка потери соединения. А теперь байткод:

Наверное ни для кого уже не секрет, что лимит инлайнинга в Hostpot JVM — 35 байткод инструкций. Поэтому мы уделили некоторое внимание этому методу, чтобы сократить его и изменили его следующим образом:

Получилось довольно близко к лимиту, но все еще 36 инструкций. Поэтому мы сделали так:

Выглядит проще. Неправда ли? На самом деле, этот код хуже предыдущего — 45 инструкций.
Еще одна попытка:

Обратите внимание на использование унарного ИЛИ (|). Это отличный пример жертвования теоретической производительностью (так как в теории || будет быстрее) ради реальной производительности (так как метод теперь будет заинлайнен). Байткод результата:

Как раз ниже лимита в 35 байткод инструкций. Это маленький метод и на самом деле даже не высоконагруженный, но идею Вы поняли. Небольшие методы не только позволяют JITу встраивать их в код, они так же означают меньше фактических машинных инструкций, что увеличивает количество кода, который поместится в L1 кэше процессора. Теперь умножьте все это на количество таких изменений в нашей библиотеке и Вы поймете почему HickaryCP действительно быстр.

Микро оптимизации

В HikariCP много микро оптимизаций. По отдельности они, конечно же, не делают картины. Но все вместе сильно увеличивают общую производительность. Некоторые из этих оптимизаций — это доли микросекунды для миллионов вызовов.

ArrayList

Одной из самых не тривиальных оптимизаций было удаление коллекции ArrayList в классе ConnectionProxy, которая использовалась для отслеживания открытых объектов Statement. Когда Statement закрывается, он должен быть удален из этой коллекции. Также, в случае если закрывается соединение — нужно пройтись по коллекции и закрыть любой открытый Statement и уже после — очистить коллекцию. Как известно ArrayList осуществляет проверку диапазонов индекса на каждый вызов get(index). Но, так как мы можем гарантировать выбор правильного индекса — эта проверка излишня. Также, реализация метода remove(Object) осуществляет проход от начала до конца списка. В тоже время общепринятый паттерн в JDBC — или сразу закрывать Statements после использования или же в порядке обратном открытию (FILO). Для таких случаев, проход, который начинается с конца списка — будет быстрее. Поэтому мы заменили ArrayList на FastStatementList в котором нету проверки диапазонов и удаление элементов из списка начинается с конца.

Медленный синглтон

Для того, чтобы сгенерировать прокси для объектов Connection, Statement, ResultSet HikariCP изначально использовал фабрику синглтонов. В случае, например, ConnectionProxy эта фабрика находилось в статическом поле PROXY_FACTORY. И в коде было несколько десятков мест, которые ссылались на это поле.

В байткоде это выглядело так:

Вы можете увидеть, что первым идет вызов getstatic, чтобы получить значение статического поля PROXY_FACTORY. Так же обратите внимание на последний вызов invokevirtual для метода getProxyPreparedStatement() объекта ProxyFactory.
Оптимизация заключалась в том, что мы удалили фабрику синглтонов и заменили ее классом со статическими методами. Код стал выглядеть так:

Где getProxyPreparedStatement() — статический метод класса ProxyFactory. А вот так выглядит байткод:

Здесь следует обратить внимание сразу на 3 момента. Вызова getstatic больше нету. invokevirtual был заменен на invokestatic, который в свою очередь лучше оптимизируется виртуальной машиной. И последний момент, который трудно заметить — размер стека уменьшился с 5-ти элементов до 4-х. Так как до оптимизации в случае с invokevirtual на стек должна так же прийти ссылка на сам объект ProxyFactory. Это значит и дополнительную pop инструкцию для получения этой ссылки из стека в момент вызова getProxyPreparedStatement(). В общем, если просуммировать, то мы избавились от доступа к статическому полю, убрали лишние операции push и pop на стеке и сделали вызов метода более пригодным для оптимизации JIT.

UPDATE:
В комментариях часть статьи «Медленный синглтон» вызвала много обсуждений. apangin утверждает, что все эти микро оптимизации бессмысленны и не дают никакого прироста. В коментарии приводится простой бенчмарк одинаковой стоимости invokeVirtual и invokeStatic. А тут бенчмарк пула соединений одноклассников, который якобы в 4 раза быстрее HickaryCP. На что автор HickaryCP дает следующий ответ:

First I would like to comment on @odnoklassniki comment that their pool is 4x faster. I have added their pool to the JMH benchmark and committed the changes for anyone to run. Here is the result vs. HikariCP:

This is showing HikariCP at 8x faster than one-datasource.

Keep in mind that not only has HikariCP changed since that wiki page was written, but the JMH test harness itself has changed. In order to recreate the results I got at that time, I checked out HikariCP source with that specific commit, and checked out the source just before that commit. I ran both using the benchmark harness available at that time:

Before static proxy factory methods:

After static proxy factory methods:

It shows a minor improvement after the change that is above the mean error.

Typically, every change is checked with the benchmark before being committed, so it is doubtful that we would have committed that change unless the benchmark showed improvement.

EDIT: And wow has HikariCP performance improved since January 2014!

Источник

Простейший Connection pool без DataSource в Java

Ни для кого не секрет, что в Java EE Connection Pool реализуется используя Data Source. С примером реализации в Apache Tomcat можно ознакомиться по этой ссылке: habrahabr.ru/post/101342. Но что делать, если мы используем только Java SE и нам нужно организовать многопоточный доступ к базе данных по схеме Connection Pool. Ведь сервера приложений у нас в данном случае нет, следовательно, использовать Data Source мы не можем, а для создания соединений к бд нам придется скорее всего использовать java.sql.DriverManager. Можно еще использовать в замену данному подходу что-нибудь из этой статьи: docs.oracle.com/javase/jndi/tutorial/ldap/connect/pool.html. Скорее всего кем-то данный подход уже реализовывался на Java, по крайней мере я не обнаружил такую реализацию в сети. И я решил изобрести свой велосипед. Было бы хорошо, если в поисковике при поиске Connection pool в Java выходила ссылка на эту статью, дополненную и отредактированную по комментариям и дополнениям от habr.ru, и эта статья была бы полезна кому-нибудь. Если стало интересно, то прошу под кат.

Реализуем все в виде класса, конструктор которого принимает на вход начальное количество соединений в пуле и параметры подключения к бд (название загружаемого класса из драйвера и строка подключения вместе с именем пользователя и паролем). Назовем класс ConnectionPool, его конструктор будет иметь вид:

url — это строка подключения, для MS SQL Server она будет иметь вид наподобие: jdbc:sqlserver://192.168.0.1;databaseName=dbname;username=username;password=pwd. Можно разделить имя пользователя и пароль, передавать их отдельно в DriverManager. Здесь все в одном месте, по крайней мере мне так показалось удобней. Один из допустимых драйверов для работы с MS SQL Server имеет следующий вид: com.microsoft.sqlserver.jdbc.SQLServerDriver.
В данном классе должны объявляться два вектора:

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

В конструкторе используется функция getConnection, которая просто создает новое подключение. Его реализация следующая:

Итак, мы имеем вектор availableConns, заполненный Connection’ами в количестве initConnCnt штук, ни один из которых пока не используется непосредственно по назначению, т.е. для доступа к бд. Теперь напишем функцию retrieve, эта функция забирает из availableConns очередной Connection и добавляет его в usedConns, затем возвращает это соединение, тем самым он становится используемым:

Логика понятна: сначала мы проверяем, есть ли свободные соединения, если нет, то мы создаем новое подключение, если есть, то мы извлекаем последний элемент из availableConns и удаляем его из вектора свободных соединений. Затем мы только что созданное соединение или извлеченное из списка свободных добавляем в список используемых строкой
и возвращаем это соединение. Конечно же без synchronized не обойтись. Как же иначе? Доступ то многопоточный, вдруг двум потокам выделится одно и то же соединение! Когда соединение становится не нужным, то мы выполняем обратную операцию, иначе говоря putback:

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

Полностью весь класс:

upd. изменил putback согласно комментарию.

Источник

Русские Блоги

Вводное руководство ADO.NET (пять) подробный пул соединений с базой данных

Отступление

Изучив несколько первых глав, мне интересно, есть ли у вас определенное понимание ADO.NET. Независимо от качества статьи, необходимо подтвердить, что я пишу каждую статью от души. Я много думал как над макетом, так и над выбором контента. Я надеюсь, что благодаря этой серии статей, независимо от того, являетесь ли вы новичком или ветераном, вы сможете что-то приобрести в ADO.NET.Если вы сочтете это полезным, я надеюсь получить ваши рекомендации и внимание, и дайте мне знать, что вы подтверждаете меня. Если все считают, что я плохо пишу, я также рад выслушивать критику и позволяю нам вместе добиваться прогресса.

Резюме

оглавление

1. Что такое пул соединений?

Фактически, ADO.NET уже предоставил нам метод оптимизации, называемый пулом соединений.Пул соединений является таким контейнером: он хранит определенное количество физических подключений к серверу базы данных.Поэтому, когда нам нужно подключиться к серверу базы данных, нам нужно только удалить простаивающее соединение из пула (контейнера) вместо создания нового соединения. Таким образом, мы можем значительно снизить накладные расходы на подключение к базе данных, тем самым улучшив производительность приложения.

PS:Изначально я сделал две фотографии для описания пула соединений, но компания установила программное обеспечение для мониторинга и не может его загрузить, поэтому мне остается только ждать, когда у меня будет время загрузить его в следующий раз.

2. Как работает пул подключений

2.1 Создание пула подключений

Это должно быть записано,Пул соединений различается по категориям.Другими словами, в одном домене приложения может быть одновременно несколько пулов подключений разных типов. Итак, как различаются пулы соединений? В деталях, он отличается подписью процесса, доменом приложения, строкой подключения и идентификатором Windows (при использовании интегрированной безопасности). Но для того же домена приложения он обычно различается только строкой подключения. Если при открытии соединения подпись типа соединения не соответствует типу существующего пула соединений, создается новый пул соединений. В противном случае новый пул соединений не создается.

Типичный пример создания подключения:

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

В приведенном выше примере я создал три объекта SqlConnection, но для управления необходимы только два пула соединений. Возможно, внимательный друг обнаружилСтрока подключения conn1 и conn3 одинакова, поэтому вы можете использовать общий пул соединений, а conn2 отличается от conn1 и conn3, поэтому вам необходимо создать новый пул соединений.

2.2 Распределение незанятых соединений

Когда пользователь создает запрос на подключение или вызывает объект Open of the Connection,Диспетчер пула соединений сначала должен найти пул соединений соответствующего типа в соответствии с сигнатурой типа запроса на соединение, а затем попытаться выделить незанятое соединение.Подробности следующие:

2.3 Удалить недопустимое соединение

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

2.4 Утилизация использованных соединений

Когда мы заканчиваем использовать соединение, мы должны закрыть или разорвать соединение вовремя, чтобы соединение можно было вернуть в пул для повторного использования.Мы можем закрыть соединение с помощью метода Close или Dispose объекта Connection или с помощью оператора using в C #.

3. Расскажите о нескольких очень важных атрибутах.

Поведение пула соединений можно контролировать с помощью строки подключения, В основном включает четыре важных атрибута:

Или посмотрите на пример, чтобы понять свойства пула соединений. код показан ниже:

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

4. Исключение пула соединений и метод обработки

Когда пользователь открывает соединение, но не закрывает его правильно или вовремя, часто возникает проблема «утечки соединения». Утечка соединения останется открытым до тех пор, пока не будет вызван метод Dispose, а сборщик мусора (GC) закроет и освободит соединение. В отличие от ADO, ADO.NET необходимо вручную закрыть используемое соединение.Важное недоразумение состоит в том, что, когда объект подключения выходит за пределы локальной области, соединение закрывается.Фактически, когда выходит за рамки,Освобождается только объект подключения, но не ресурс подключения.Что ж, давайте сначала рассмотрим пример.

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

Чтобы сделать результат более очевидным, я установил максимальное количество подключений на 5 и период ожидания на 1 секунду. После бега быстро достигаются следующие результаты.

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

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

5. Методы мониторинга состояния подключения SQL Server.

(1) Через монитор активности

первый шаг:Откройте MSSMS Manager, нажмите «Монитор активности«икона.

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

Второй шаг:В представлении «Открыть монитор активности» щелкните «процесс«Таб.

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

третий шаг:Бежать# 4 Исключение пула соединений и метод обработки В примере в вы можете увидеть 5 открытых соединений, как показано на рисунке ниже.

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

(2) Используйте операторы T-SQL

Аналогично, выполняя системные хранимые процедурыsp_who, Мы также можем отслеживать статус подключения.

Можно получить следующие результаты:

Что такое пул соединений. Смотреть фото Что такое пул соединений. Смотреть картинку Что такое пул соединений. Картинка про Что такое пул соединений. Фото Что такое пул соединений

6. Основные принципы эффективного использования пула соединений.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *