Прежде чем применять настройки - внимательно читаем. От этого зависит работоспособность системы


Для ускорения работы системы, предусмотрено создание пулов для FCGI

Зачем это нужно

Сейчас веб-интерфейс работает так:

nginx -> fcgiwrap -> НОВЫЙ perl-процесс на КАЖДЫЙ HTTP-запрос.

Каждый такой процесс заново:

  1. компилирует index.cgi и ~45 модулей биллинга (~1.5 МБ кода);
  2. читает файлы локализации (770 КБ);
  3. подключается к БД;
  4. отдаёт ответ и УМИРАЕТ.

Между запросами НИЧЕГО не сохраняется. Каждый клик = «холодный старт». Это ~0.2 с чистой компиляции + загрузка модулей на КАЖДЫЙ клик.

ЧТО МЫ НЕ МЕНЯЕМ (важно!):

  • Многопоточность/множество воркеров — СОХРАНЯЕТСЯ. (Много операторов одновременно, изоляция SNMP-зависаний — всё работает.)
  • Изоляция процессов — СОХРАНЯЕТСЯ (каждый запрос = отдельный процесс).
  • Логика биллинга — НЕ МЕНЯЕТСЯ.
  • Данные из/в БД — НЕ МЕНЯЮТСЯ.

Как это работает

(модель «пул воркеров», как fcgiwrap -c N)

  Родительский процесс (демон acp-fcgi-index):

  • ОДИН РАЗ компилирует модули биллинга (через require).
  • Скомпилированный код остаётся в памяти.
  • Создаёт слушающий UNIX-сокет /run/acp-fcgi-index/index.sock.
  • Форкает N воркеров (ACP_FCGI_MAX_WORKERS).
  • Следит за воркерами и перезапускает упавших.

  Воркер (дочерний процесс):

  • Создаёт СВОЙ FCGI::Request на общем слушающем сокете.
  • Крутит свой цикл Accept(): ядро само распределяет запросы между воркерами. N воркеров = N одновременных запросов.
  • Наследует скомпилированный код родителя (copy-on-write) — БЕЗ повторной компиляции.
  • На КАЖДЫЙ запрос делает fork(): ребёнок выполняет CGI в СВОЁМ чистом пространстве имён и умирает, воркер ждёт его (waitpid) и снова Accept(). Так глобальные переменные и переопределения sub НЕ переносятся между запросами (иначе «Subroutine ... redefined»).
  • Ребёнок ПЕРЕД выходом штатно закрывает соединение с БД (_close_billing_db), чтобы MariaDB не видела обрыв.

  ИТОГ: компиляция ~45 модулей и локализации происходит ОДИН РАЗ при старте демона, а не на каждый клик. Клик = только выполнение логики. Параллелизм — реальный (N одновременных запросов).

  ПОЧЕМУ НЕ «fork на каждый запрос» ВМЕСТО пула: объект FCGI::Request ОДИН на процесс и хранит состояние текущего запроса. Если родитель вызовет Accept() повторно, пока ребёнок пишет ответ через тот же $request, состояние перезапишется и ответ «развалится» (nginx отдаст 502). Поэтому параллелизм реализуется через НЕСКОЛЬКО независимых воркеров, каждый со СВОИМ $request (так делает Plack::Handler::FCGI через FCGI::ProcManager). А внутри воркера fork на каждый запрос нужен для ЧИСТОГО пространства имён.

Обратная совместимость

Реализовано так, что НИ У ОДНОГО клиента ничего не сломается:

СИТУАЦИЯ A: у клиента НЕ установлен модуль FCGI.

    -> fcgi_runner.pl тихо откатывается в обычный CGI-режим.
    -> Работает как раньше (одноразовый запуск). Ничего не ломается.

СИТУАЦИЯ B: у клиента Apache (не nginx).

    -> Apache просто НЕ использует fcgi_runner.pl и systemd-юниты.
    -> Работает по-старому через свой CGI-обработчик. Ничего не ломается.

СИТУАЦИЯ C: скрипт запущен не через FastCGI (вручную, fcgiwrap, mod_cgi).

    -> Раннер определяет это по переменной GATEWAY_INTERFACE.
    -> Откатывается в обычный CGI-режим. Ничего не ломается.

СИТУАЦИЯ D: у клиента nginx + FCGI (наш случай).

    -> Полный эффект ускорения.

  ВЫВОД: наличие/отсутствие FCGI и тип веб-сервера НЕ ломают систему. Файл fcgi_runner.pl можно безопасно использовать — он безвреден для тех, кто его не использует.

Описание запуска установки

/usr/acp/misc/install_fcgi_pool.sh

Скрипт:

  • проверит FCGI;
  • скопирует раннер в /usr/acp/cgi-bin/;
  • установит юниты acp-fcgi-index и acp-fcgi-admin;
  • запустит сервисы;
  • проверит, что сокеты созданы.

Ожидаемый вывод в конце:

    [OK] Сокет создан: /run/acp-fcgi-index/index.sock
    [OK] Сокет создан: /run/acp-fcgi-admin/index.sock
    === УСТАНОВКА ЗАВЕРШЕНА ===

Проверка


systemctl status acp-fcgi-index
systemctl status acp-fcgi-admin
journalctl -u acp-fcgi-index -n 30


  Сервисы должны быть active (running), сокеты — существовать.

Дополнительная информация

  1. Открыть клиентский веб-интерфейс — должен работать как обычно.
  2. Открыть админку — должна работать как обычно.
  3. Проверить логи: 
      journalctl -u acp-fcgi-index -n 50
       journalctl -u acp-fcgi-admin -n 50

Не должно быть ошибок.