Пакет · cpool

CPool

Пул берёт на себя выдачу и возврат соединений, потолок их числа, срок жизни и проверку живости. Что именно лежит в пуле, он не знает — это задаёт адаптер из трёх методов. Поэтому один и тот же пул обслуживает и базу, и Redis, и что угодно ещё.

Требует PHP 8.4+Зависимости нетSwoole опционально

Зачем нужен пул

Проблема. В классическом PHP процесс обслуживал один запрос и умирал, поэтому соединение открывали заново каждый раз и об этом не думали. Резидентный воркер живёт неделями и обслуживает много запросов одновременно — и тут открывать соединение на каждый запрос становится дорого, а держать одно общее нельзя: соединение это сокет с последовательным протоколом, и два запроса через него пойдут вперемешку.

Решение. Держать набор готовых соединений и выдавать их по одному. Запрос берёт соединение, работает, возвращает. Соединения переиспользуются, их число ограничено сверху, а мёртвые заменяются.

Проблема не в базе, а в рантайме

Пул нужен не потому, что база медленная, а потому, что процесс перестал умирать после запроса. Под PHP-FPM пул не нужен и не даёт ничего — там процесс и так обслуживает одну единицу работы за раз.

Что делает этот пакет

  • Ограничивает число соединений. Тысяча одновременных запросов не превращается в тысячу соединений — они встают в очередь, и падает не база, а один запрос по таймауту.
  • Выдаёт живые соединения. Простоявшее соединение проверяется перед выдачей и заменяется, если умерло. Перезапуск базы перестаёт быть отравлением воркера.
  • Следит за возрастом. Соединения старше maxLifetime уходят на покой — так пул успевает за инфраструктурой, которая двигается под ним (прокси, failover-адреса).
  • Работает в обоих рантаймах. Под Swoole — настоящий пул на корутинах; без него — SingleConnection с тем же контрактом. Вызывающий код не ветвится.

Чего он не делает

Пакет не знает ни одного драйвера. В нём нет ни PDO, ни Redis, ни SQL, ни протоколов. Он оперирует объектами, которые ему отдал адаптер, и умеет ровно три вещи: создать, проверить, закрыть.

Из этого следует и главное ограничение: пул не управляет состоянием соединения. Незакрытая транзакция или переключённая база Redis уедут вместе с соединением к следующему заёмщику — это забота вызывающего.

Кому он нужен напрямую

Обычно — никому: в приложении вы пользуетесь не пулом, а тем, что построено поверх него (PPA для базы, winter-redis для Redis). Напрямую CPool берут, когда нужно подключить к пулу свой источник соединений — другую СУБД, внешний сервис, брокер очередей.

Ключевые понятия

  • ConnectionFactory — адаптер: create(), validate(), close(). Единственное место, знающее о драйвере.
  • ConnectionPool — сам пул: выдать, вернуть, выселить.
  • PoolEntry — выданное соединение вместе с его временными метками.
  • SingleConnection — тот же контракт для рантайма без конкуренции.
  • PoolPolicy — неизменяемые настройки: потолок, таймауты, срок жизни, уборка.

Дальше