Postgres №41
В прошлых заметках мы говорили про пулы соединений вроде HikariCP. Их еще называют пулами приложения. Это библиотека, которая открывает соединения, одалживает их тредам и закрывает. Аналогично устроен пул на Питоне из состава psycopg2.
Есть, однако, другой подход – пулы на уровне сети. Запускается утилита, которая притворяется сервером Postgres (разговаривает по протоколу PG Wire). Она открывает несколько соединений к целевой базе. Как только к ней подсоединяются, она помечает одно из соединений как занятое. Далее она перекладывает сообщения от клиента серверу и обратно. Как только клиент уходит, занятое им соединение помечается свободным. Все это напоминает HTTP-прокси, только с другим протоколом. Наиболее известный PG Wire прокси – это pgbouncer; есть и другие аналоги.
Pgbouncer отлично подходит для платформ, где по каким-то причинам нет пула
приложения. Например, в PHP, многократно вызывая postgres.connect(), мы будет
соединяться с сетевым пулом, который направит сообщения в одно из заранее
открытых соединений.
Кажется, что решение идеально: поставил перед базой pgbouncer и готово:
превысить лимит подключений невозможно. Однако мне подход с pgbouncer не
нравится, и вот почему.
Во-первых, появляется бутылочное горлышко, за которым нужно следить. Если
pgbouncer или аналог отвалится, доступ к базе пропадет у всех. Сюда же
относится конфигурация: нельзя перезагрузить pgbouncer, потому что отвалятся все
клиенты.
Во-вторых, когда у каждого приложения свой пул, это дает гибкость. Скажем, одному сервису понадобилось больше соединений, второму – меньше. Это легко исправить, не затрагивая всю инфраструктуру. Потреблением базы таким образом можно управлять гранулярно.
В-третьих, pgbouncer видится мне костылем для платформ, где нет своего пула
соединений. Постоянные подключения к pgbouncer – это открытие сокета и системные
вызовы, которых можно избежать, будь у вас нормальный пул.
AWS предлагает pgbouncer за отдельную плату. Не хочешь возиться с пулами –
будь добр плати.
Итог последних трех заметок. Никогда не задирайте max_connections больше
сотни. В идеале он не превышает нескольких десятков. Изучите, как приложение
работает с базой, исправьте очевидные ошибки из прошлой заметки. Используйте пул
даже для одного соединения. Занимайте его только чтобы прочитать данные из базы;
обработка данных не должна удерживать соединение. Читайте логи пула, собирайте
метрики.
Если под вашу платформу нет пула, рассмотрите прокси вроде pgbouncer. Этот
вариант ограничивает всех клиентов без исключения. Он сложнее, поскольку
образует новый узел инфраструктуры, а значит – это потенциальная точка отказа и
мониторинг.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter