Автор оригинала: Vlad Mihalcea.
Вступление
Все проекты, над которыми я работал, использовали базу данных пул соединений , и это по очень веским причинам. Иногда мы можем забыть, почему мы используем один шаблон дизайна или определенную технологию, поэтому стоит отступить и поразмыслить над этим. Каждая технология или технологическое решение имеет как положительные, так и отрицательные стороны, и если вы не видите никаких недостатков, вам нужно задаться вопросом, чего вам не хватает.
Жизненный цикл подключения к базе данных
Для каждой операции чтения или записи базы данных требуется подключение. Итак, давайте посмотрим, как выглядит поток подключений к базе данных:
Поток идет вот так:
- Уровень данных приложения запрашивает у источника данных подключение к базе данных
- Источник данных будет использовать драйвер базы данных для открытия подключения к базе данных
- Создается соединение с базой данных и открывается TCP-сокет
- Приложение считывает/записывает данные в базу данных
- Соединение больше не требуется, поэтому оно закрыто
- Розетка закрыта
Вы можете легко сделать вывод, что открытие/закрытие соединений-довольно дорогостоящая операция. PostgreSQL использует отдельный процесс ОС для каждого клиентского подключения, поэтому высокая скорость открытия/закрытия соединений создаст нагрузку на вашу систему управления базами данных.
Наиболее очевидными причинами повторного использования подключения к базе данных были бы:
- сокращение накладных расходов на ввод-вывод ОС системы управления приложениями и базами данных для создания/уничтожения TCP-соединения
- сокращение мусора объектов JVM
Объединение против отсутствия объединения
Давайте сравним, как решение без объединения сравнивается с HikariCP который, вероятно, является самым быстрым пулом соединений доступной платформой.
Тест откроет и закроет 1000 соединений.
private static final Logger LOGGER = LoggerFactory.getLogger(
DataSourceConnectionTest.class
);
private static final int MAX_ITERATIONS = 1000;
private Slf4jReporter logReporter;
private Timer timer;
protected abstract DataSource getDataSource();
@Before
public void init() {
MetricRegistry metricRegistry = new MetricRegistry();
this.logReporter = Slf4jReporter
.forRegistry(metricRegistry)
.outputTo(LOGGER)
.build();
timer = metricRegistry.timer("connection");
}
@Test
public void testOpenCloseConnections() throws SQLException {
for (int i = 0; i < MAX_ITERATIONS; i++) {
Timer.Context context = timer.time();
getDataSource().getConnection().close();
context.stop();
}
logReporter.report();
}
Объединение пулов соединений во много раз быстрее, чем альтернатива без объединения .
| Metric | DB_A (ms) | DB_B (ms) | DB_C (ms) | DB_D (ms) | HikariCP (ms) | |--------|-----------|-----------|-----------|-----------|---------------| | min | 11.174 | 5.441 | 24.468 | 0.860 | 0.001230 | | max | 129.400 | 26.110 | 74.634 | 74.313 | 1.014051 | | mean | 13.829 | 6.477 | 28.910 | 1.590 | 0.003458 | | p99 | 20.432 | 9.944 | 54.952 | 3.022 | 0.010263 |
Почему объединение происходит намного быстрее?
Чтобы понять, почему решение для объединения в пул работает так хорошо, нам необходимо проанализировать процесс управления соединениями в пул:
Всякий раз, когда запрашивается подключение, источник данных пула будет использовать пул доступных подключений для получения нового подключения. Пул будет создавать новые соединения только в том случае, если доступных соединений не осталось и пул еще не достиг своего максимального размера. Метод соединения с пулом close() вернет соединение в пул, вместо того чтобы фактически закрыть его.
Быстрее и безопаснее
Пул соединений действует как ограниченный буфер для входящих запросов на подключение. Если произойдет скачок трафика, пул подключений выровняет его, вместо того чтобы насыщать все доступные ресурсы базы данных.
Шаг ожидания и механизм тайм-аута являются защитными крючками, предотвращающими чрезмерную нагрузку на сервер базы данных. Если одно приложение получает слишком много трафика базы данных, пул подключений уменьшит его, следовательно, предотвратит отключение сервера базы данных (следовательно, повлияет на всю корпоративную систему).
С большой властью приходит большая ответственность
Все эти преимущества имеют свою цену, материализующуюся в дополнительной сложности конфигурации пула (особенно в крупных корпоративных системах). Так что это не серебряная пуля, и вам нужно обратить внимание на многие настройки пула, такие как:
- минимальный размер
- максимальный размер
- максимальное время простоя
- время ожидания получения
- время ожидания повторных попыток
Моя следующая статья будет посвящена предприятию объединению подключений проблемы и как Flexipool может помочь вам найти правильные размеры бассейна.
Код доступен на GitHub .