PgBouncer используют, чтобы сократить дорогие коннекты к postgres:

Если Client (Application) запускается Х раз в секунду, он делает Х подключений к PgBouncer, что в итоге превращается например в 2 запроса к PosgreSQL DB Server.
Например в php-pfm в среднем прилетает 5 запросов в секунду:

Таким образом мы получим 5 подключений к PgBouncer.
Но, если каждый из 5 запросов будет работать 2 секунды, то в PgBouncer мы увидим 10 подключений в Connection Pool.
Если в php-pfm прилетит 65 запросов, каждый из которых будет работать 2 секунды, то мы получим 130 подключений в Connection Pool и тогда в PgBouncer сработает настройка:
default_pool_size (для всех user/database пар он одинаковый) = 128 подключений
По идее все что свыше 128 подключений PgBouncer отбросит сразу, но практика показала, что он все же принимал подключения и переводил их в статус idle (простаивающие, в прочем как и остальные, которые были созданы в рамках ограничения в 128 штук, но которые PgBouncer не мог обслужить потому что, PosgreSQL не успевал).
В теории, если в pgbouncer увеличить pool_size для "user/database пары", то это поможет PgBouncer-у держать больше idle подключений, что в свою очередь скажется на возможности держать рабочими еще большее количество php-fpm процессов, что в свою очередь поможет породить еще больше k8s-подов для php-pfm (но у нас в k8s стоит настройка максимума: 10 подов и это хорошо, а то бы все ресурсы бы утилизировались и ущерб был бы катастрофическим).
Итог:
По идее k8s может реализовать стратегию Circuit Breaker Pattern самостоятельно с помощью readiness probe, но:
Когда шаг 3 выполнен, но запросы в приложение идут, k8s создает новые pod-ы до тех пор, пока не будет достигнуть максимальный лимит создания pod-ов в k8s.
Когда все поды в статусе "проверка readiness probe" (поды без трафика), на каком-то поде может пройти readiness probe и:
Дальше все выше указанные 5 пунктов могут повториться но уже с другой подой, но это уже не важно, ведь если приложение или инфраструктура не может выдержать такую большую почти мгновенную нагрузку, то тут может помочь только постепенное понижение/увеличение трафика, но k8s так делать не умеет.
Получается k8s не панацея и нужно учить приложение анализировать свой состояние и на основе этих показателей постепенно уменьшать/увеличивать трафик (таким образом сразу отклоняя запросы, которые приложение не может обслужить).
Если перед k8s поставить haproxy, умеющий увеличивать трафик медленно (см. настройку slowstart), то достигнем желаемого.
Однако запросы внутри k8s не ходят через внешний haproxy, трафик внутри k8s ходит от к сервиса к сервису напрямую, а значит haproxy не поможет.
Предположим, мы имеем:
Давайте превратим 10 подов в:
Теперь k8s.sheduler будет реализовывать Circuit Breaker распределяя 100% трафика на 100 подов (каждому по 1% трафика).
Вуаля k8s.sheduler будет делать readiness probe на каждом поде и будет постепенно увеличивать трафик (и уменьшать тоже).
Да, этот подход спасет от ситуации, когда большое количество трафика пойдет на один под, ведь один маленький под сможет обслужить только небольшое количество трафика исходя из маленького количества ресурсов (таким образом база не будет нагружена большим количеством запросов в следствии небольшого количества запросов к поду).
Минусы:
Комментарии
Комментариев пока нет.