База данных всегда была нашим слабым местом. Обычно нам приходится обрабатывать сотни или тысячи сообщений в минуту, и нам разрешено использовать только дюжину подключений к БД. Большинство запросов выполняются быстро (миллисекунды), но некоторые могут занимать соединение в течение нескольких секунд.
Наше типичное решение:
- Семафор емкостью N
- ThreadPoolExecutor с количеством потоков N
- Пул соединений N + 1 и JDBC (1 соединение зарезервировано для Heartbeat/liveness проба)
Это работает достаточно хорошо, но теперь пришло время масштабирования — мы собираемся обрабатывать миллионы сообщений, и мне интересно, что поможет нам лучше использовать ресурсы. У нас по-прежнему есть ограничения в 10–50 одновременных подключений к базе данных, и мы должны обрабатывать сообщения как можно быстрее, в идеале с одинаковым использованием ЦП/памяти, но, как я уже говорил, узким местом является ограниченный пул соединений, а не нехватка ресурсов на уровне приложения.
Я рассматриваю два решения и, возможно, их сочетание:
- Виртуальные потоки + блокировка JDBC
- Драйвер реактивной БД (клиент Vert.x pg, поскольку соседняя команда имеет опыт работы с ним, но возможны и другие решения)
Что происходит, когда виртуальный поток отправляет запрос к базе данных и приостанавливается? Будет ли соединение JDBC освобождено для обработки других запросов/ответов во время ожидания ответа на первый запрос? Или он все еще будет занят из-за блокирующего характера драйвера JDBC (поэтому потоки платформы готовы выполнять больше задач, а пул соединений - нет, поскольку все соединения заняты)?
Мне тоже не ясно, как на самом деле работают реактивные драйверы базы данных. Что произойдет, когда они отправят запрос к БД (отправят последний байт в сеть) - вернется ли соединение в пул? Если да, то как БД управляет контекстами сеансов для множества запросов и ответов, отделенных друг от друга в этом асинхронном взаимодействии?..
Мобильная версия