惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
T
Tor Project blog
G
GRAHAM CLULEY
S
Security Affairs
P
Palo Alto Networks Blog
TaoSecurity Blog
TaoSecurity Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
aimingoo的专栏
aimingoo的专栏
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 三生石上(FineUI控件)
Cloudbric
Cloudbric
Cyberwarzone
Cyberwarzone
A
About on SuperTechFans
Microsoft Azure Blog
Microsoft Azure Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CERT Recently Published Vulnerability Notes
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Check Point Blog
宝玉的分享
宝玉的分享
Forbes - Security
Forbes - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Security Blog
Microsoft Security Blog
Schneier on Security
Schneier on Security
The Last Watchdog
The Last Watchdog
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
H
Heimdal Security Blog
Recorded Future
Recorded Future
L
LangChain Blog
WordPress大学
WordPress大学
Know Your Adversary
Know Your Adversary
C
Cyber Attacks, Cyber Crime and Cyber Security
V
Visual Studio Blog
B
Blog
H
Help Net Security
T
Tailwind CSS Blog
The Hacker News
The Hacker News
雷峰网
雷峰网
P
Proofpoint News Feed
博客园 - Franky
Attack and Defense Labs
Attack and Defense Labs
有赞技术团队
有赞技术团队
S
Schneier on Security
T
Troy Hunt's Blog
云风的 BLOG
云风的 BLOG
Hacker News - Newest:
Hacker News - Newest: "LLM"
Blog — PlanetScale
Blog — PlanetScale
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Proofpoint News Feed

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Оптимизируем JDBC connection pool HikariCP. Прод, ресурсы и типовые ошибки
rurikovich · 2026-05-05 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение7 мин

Охват и читатели13K

Туториал

Привет, Хабр!

Это продолжение первой части: там были основы HikariCP, версии, примеры настройки на JVM-языках, Spring Boot и разбор главных параметров пула. Здесь разберём, как считать размер пула, что учитывать в Kubernetes и при нескольких сервисах, как улучшить «типовой» конфиг из начала серии, типовые ошибки, мини-чеклист для прода и ссылки.

Стартуем сразу с п.7, Погнали !

7. Как выбрать размер пула

Известная формула из PostgreSQL wiki и HikariCP wiki

Есть известная формула из PostgreSQL wiki и HikariCP wiki:

connections = (core_count * 2) + effective_spindle_count

core_count - ядра сервера базы, не приложения. Hyper-threading лучше не считать как полноценные ядра.

effective_spindle_count - грубая поправка на дисковую подсистему. Для современных SSD/NVMe часто берут 0 или 1 как стартовое приближение.

Пример:

PostgreSQL: 8 физических ядер, SSD
pool target ~= (8 * 2) + 1 = 17 активных соединений

Звучит мало. Особенно если у вас 500 RPS.

Но соединения к базе это не пользователи и не HTTP-запросы. Если запрос к базе занимает 20 мс, то 10 соединений теоретически могут прокачать сотни операций в секунду. А если запрос занимает 2 секунды, пул на 100 соединений не спасёт. Он просто даст ста людям одновременно страдать внутри базы.

Есть ещё один полезный способ думать: Little's Law

Есть ещё один полезный способ думать: Little’s Law.

нужные соединения ~= RPS * среднее время работы с БД

Если сервис делает 300 DB-операций в секунду, а среднее время удержания соединения 30 мс:

300 * 0.03 = 9 соединений

Добавили запас, проверили p95/p99, прогнали нагрузочный тест. Получили стартовую настройку.

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

  • заняты почти все соединения в пуле;

  • потоки часто ждут свободное соединение;

  • растёт количество ошибок по connection timeout;

  • увеличивается время получения соединения из пула;

  • при этом сама база не перегружена по CPU, IO и блокировкам.

Если pending растёт, а база уже перегружена, увеличение пула сделает хуже. Это классика: приложение начинает давить сильнее ровно в тот момент, когда базе нужна передышка.


8. Несколько приложений и Kubernetes

Размер пула надо считать не только на один процесс, а на всю систему

Один из самых частых продовых сюрпризов:

maximumPoolSize = 32
replicas = 12
итого потенциально 384 соединения к базе

А ещё есть миграции, админки, BI, cron jobs, ручные подключения, read-only сервисы. Потом кто-то удивляется, почему PostgreSQL внезапно выдает too many connections.

Размер пула надо считать не только на один процесс, а на всю систему:

db_connection_budget = 160
service_replicas = 8
pool_per_replica = 160 / 8 = 20
Если используйте HPA (Horizontal Pod Autoscaler), например PgBouncer

Если есть HPA (Horizontal Pod Autoscaler), берите максимальное количество pod’ов, а не комфортное среднее в обеденное время.

И да, иногда правильный ответ не “увеличить HikariCP”, а поставить PgBouncer или другой внешний pooler. Особенно когда много приложений, много коротких запросов и PostgreSQL страдает от числа backend-процессов.

PgBouncer это лёгкий внешний пулер соединений для PostgreSQL. Он стоит между приложениями и базой, принимает много клиентских подключений и переиспользует меньшее число реальных соединений к PostgreSQL.

Проще говоря, HikariCP управляет соединениями внутри одного JVM-приложения, а PgBouncer помогает ограничить общее количество соединений к базе на уровне инфраструктуры.


9. Что бы я поменял в настройке из первой части статьи

Стартовая конфигурация была такая:

Фрагмент стартовой конфигурации
val config = new HikariConfig()
config.setJdbcUrl(url)
config.setUsername(user)
config.setPassword(password)
config.setMaximumPoolSize(connectionPoolMaxSize)
config.setLeakDetectionThreshold(1000)
config.setAutoCommit(true)
sslRootCert.foreach(config.addDataSourceProperty("sslrootcert", _))

new HikariDataSource(config)

И maxSize = 32.

Я бы сделал несколько вещей.

Обновил версию HikariCP

Если проект всё ещё на HikariCP 3.4.5, это 2020 год. Для JVM-проекта в 2026 это уже техдолг.

Но обновление зависит от Java:

  • Java 11+ - смотреть HikariCP 7.x или актуальную поддерживаемую линию фреймворка.

  • Java 8 - не прыгать на 7.x, а сначала разобраться с совместимой веткой и планом миграции JVM.

  • Java 21 + virtual threads - обязательно нагрузочное тестирование, особенно если соединения часто создаются и закрываются.

Убрал или исправил leak detection

1000 мс выглядит как ошибка. Я бы сделал так:

if (leakDetectionEnabled) {
  config.setLeakDetectionThreshold(10_000)
}

И включал бы это через env/config только на время диагностики. Для постоянного прода лучше метрики плюс алерты на pending, timeout, usage.

Задал poolName

Без имени пула метрики и логи хуже читаются.

config.setPoolName("app-postgres-main")

Название должно быть обезличенным, но понятным: сервис, база, роль. Если есть read-only пул, он должен называться иначе.

Явно настроил таймаут ожидания соединения

30 секунд по умолчанию я бы не оставлял.

config.setConnectionTimeout(5000)
config.setValidationTimeout(2000)

Для API 5 секунд это уже много. Для background jobs можно задать отдельно.

Настроил maxLifetime и keepaliveTime

Например:

config.setMaxLifetime(25 * 60 * 1000)
config.setKeepaliveTime(2 * 60 * 1000)

Но эти числа нельзя копировать без проверки. Надо смотреть реальные таймауты PostgreSQL, cloud DB, firewall, NAT, proxy, PgBouncer, service mesh. maxLifetime должен быть чуть меньше внешнего лимита.

Подумал над minimumIdle

Если сервис online и нагрузка более-менее постоянная, я бы начал с fixed-size:

config.setMaximumPoolSize(poolSize)
config.setMinimumIdle(poolSize)

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

Подключил метрики

Для Spring Boot это Actuator/Micrometer. Для ручной конфигурации:

config.setMetricRegistry(meterRegistry);

или JMX:

config.setRegisterMbeans(true);

Я бы не выпускал сервис в прод без графиков:

  • active connections;

  • idle connections;

  • pending threads;

  • connection acquire time;

  • connection usage time;

  • connection timeout count.

Пересчитал maxSize = 32

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

Минимальный sanity-check:

max_db_connections_for_service / max_replicas

Потом сверка с базой:

(db_cores * 2) + effective_spindle_count

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


10. Пример более полного конфига

В HOCON это могло бы выглядеть так:

Пример более полного HOCON-конфига
db.jdbc {
  dataSource {
    url = ${?DATASOURCE_URL}
    user = ${?DB_USER}
    password = ${?DB_PASSWD}
  }

  connectionPool {
    poolName = "app-postgres-main"
    maxSize = 16
    minIdle = 16
    connectionTimeoutMs = 5000
    validationTimeoutMs = 2000
    maxLifetimeMs = 1500000
    keepaliveTimeMs = 120000
    leakDetectionThresholdMs = 0
    registerMbeans = true
  }
}

И код:

Пример более полной конфигурации
val config = new HikariConfig()
config.setJdbcUrl(jdbc.url)
config.setUsername(jdbc.user)
config.setPassword(jdbc.password)

config.setPoolName(pool.poolName)
config.setMaximumPoolSize(pool.maxSize)
config.setMinimumIdle(pool.minIdle)
config.setConnectionTimeout(pool.connectionTimeoutMs)
config.setValidationTimeout(pool.validationTimeoutMs)
config.setMaxLifetime(pool.maxLifetimeMs)
config.setKeepaliveTime(pool.keepaliveTimeMs)
config.setLeakDetectionThreshold(pool.leakDetectionThresholdMs)
config.setRegisterMbeans(pool.registerMbeans)
config.setAutoCommit(true)

sslRootCert.foreach(config.addDataSourceProperty("sslrootcert", _))

new HikariDataSource(config)

Опять же, это не “идеальный конфиг для всех”. Просто в нём видно, какие настройки выбраны и зачем.


11. Типовые ошибки

Слишком большой пул

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

Один конфиг для API и batch

API хочет fail fast. Batch может подождать. API держит соединение миллисекунды. Batch может держать секунды или минуты. Разные профили нагрузки иногда требуют разных пулов или хотя бы разных таймаутов.

Не закрывать соединения

В Java это try-with-resources.

try (Connection connection = dataSource.getConnection()) {
    // SQL work
}

В Spring - нормальные транзакции и отсутствие ручного удержания connection где попало.

В функциональных JVM-стеках - Resource, ZLayer и другие managed lifecycle-подходы. В Clojure - with-open, если берёте connection руками.

Полагаться только на connectionTestQuery

Для нормальных JDBC4-драйверов HikariCP умеет использовать Connection.isValid(). Ручной SELECT 1 часто не нужен. Иногда нужен, если драйвер старый или странный, но это уже исключение.

Не знать таймауты инфраструктуры

База, firewall, NAT gateway, cloud proxy, PgBouncer, service mesh - всё это может закрывать неактивные соединения по своим правилам. Если Hikari узнаёт о смерти соединения последним, пользователи получают ошибки.


12. Мини-чеклист для прода

Мини-чеклист для прода

Перед тем как считать настройку HikariCP законченной, я бы прошёлся по такому списку:

  • версия HikariCP совместима с Java и фреймворком;

  • maximumPoolSize посчитан на все реплики, а не на один процесс;

  • minimumIdle выбран осознанно: fixed-size или dynamic;

  • connectionTimeout подходит под SLA сервиса;

  • maxLifetime меньше внешних connection timeout’ов;

  • keepaliveTime включён, если инфраструктура режет idle-соединения;

  • leak detection выключен или включается для дебага;

  • есть poolName;

  • есть метрики и алерты;

  • был нагрузочный тест после изменения размера пула;

  • read-only и write-пулы различаются в метриках и логах.


13. Ссылки


Вместо вывода

HikariCP хорош тем, что его легко подключить. И опасен тем же самым.

Поставил зависимость, написал maximumPoolSize = 32, сервис стартует, графики зелёные. Потом добавились реплики, вырос p95, база переехала за прокси, в соседнем сервисе включили batch, и старый “нормальный” конфиг стал миной.

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

И если это ограничение выбрано осознанно, базе проще работать стабильно под нагрузкой.


Если вам близки темы разработки, рефакторинга, архитектуры и стартапов буду рад видеть вас в моём Telegram-канале.

Успешных вам релизов!