10. Приложения FastCGI
HAProxy может отправлять запросы HTTP приложениям FastCGI с ролью Responder. Эта возможность добавлена в HAProxy 2.1. Для её использования серверы необходимо настроить на протокол FastCGI (с помощью «proto fcgi» в строке server), а в управляющем ими бэкенде нужно настроить и подключить приложение FastCGI (с помощью «use-fcgi-app» в секции прокси). Можно определить несколько приложений FastCGI, но бэкенд одновременно может использовать только одно из них.
HAProxy реализует все возможности спецификации FastCGI для приложений Responder. В частности, он может мультиплексировать несколько запросов в одном соединении.
10.1. Настройка
10.1.1. Секция fcgi-app
fcgi-app <name>
Объявляет приложение FastCGI с именем <name>. Для корректной конфигурации необходимо определить как минимум корневой каталог документов.
acl <aclname> <criterion> [flags] [operator] <value> ...
Объявляет или дополняет список контроля доступа.
Подробности см. в описании директивы «acl» в разделе 4.2 и в разделе 7 об использовании ACL. Списки ACL, определённые для приложения FastCGI, доступны только ему. Их нельзя использовать в другом приложении или прокси. Аналогично приложение FastCGI не может использовать списки ACL, определённые в других секциях. Однако предопределённые ACL доступны.
docroot <path>
Задаёт корневой каталог документов на удалённом узле. <path> используется для формирования значений по умолчанию параметров FastCGI SCRIPT_FILENAME и PATH_TRANSLATED. Это обязательная настройка.
index <script-name>
Задаёт имя скрипта, добавляемое к URI, оканчивающемуся косой чертой («/»), чтобы получить значение по умолчанию параметра FastCGI SCRIPT_NAME. Это необязательная настройка.
Пример:
log-stderr global
Включает запись в журнал сообщений STDERR, выдаваемых приложением FastCGI.
Подробности см. в описании директивы «log» в разделе 4.2 . Это необязательная настройка. По умолчанию сообщения STDERR игнорируются.
pass-header <name> [ { if | unless } <condition> ]
Задаёт имя заголовка запроса, передаваемого приложению FastCGI. После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.
Большинство заголовков запроса уже доступны приложению FastCGI с префиксом «HTTP_». Поэтому эта директива нужна только для передачи заголовков, которые намеренно исключаются. Сейчас исключаются заголовки «Authorization», «Proxy-Authorization» и заголовки, действующие только на одном участке соединения (hop-by-hop).
Обратите внимание: заголовки «Content-type» и «Content-length» никогда не передаются приложению FastCGI, поскольку уже преобразованы в параметры.
path-info <regex>
Задаёт регулярное выражение для извлечения script-name и path-info из пути после декодирования URL. <regex> может содержать две группы захвата: первая извлекает имя скрипта, вторая — path-info. Первая обязательна, вторая необязательна. Таким образом можно извлечь script-name из пути, игнорируя path-info. Это необязательная настройка. Если она не задана, сопоставление пути не выполняется, а параметры FastCGI PATH_INFO и PATH_TRANSLATED не заполняются.
Из соображений безопасности при заданном регулярном выражении в пути после декодирования URL запрещены символы перевода строки и нулевые символы. Ограничение связано с тем, что иначе сопоставление всегда завершается неудачей (из-за особенностей выполнения регулярных выражений в HAProxy). Поэтому, если после декодирования URL в пути обнаружен любой из этих двух символов, клиенту возвращается ошибка. Здесь применяется принцип наименьшего удивления.
Пример:
option get-values
Включает или отключает получение переменных управления соединениями.
При установке соединения HAProxy может отправить запись FCGI_GET_VALUES, чтобы получить значения следующих переменных:
* FCGI_MAX_REQS The maximum number of concurrent requests this
application will accept.
* FCGI_MPXS_CONNS "0" if this application does not multiplex connections,
"1" otherwise.
Некоторые приложения FastCGI не поддерживают эту возможность. Другие закрывают соединение сразу после отправки ответа. Поэтому по умолчанию этот параметр отключён.
Обратите внимание: максимальное число одновременных запросов, принимаемых приложением FastCGI, является переменной соединения. Оно ограничивает только число потоков на соединение. Если требуется ограничить общую нагрузку на приложение, необходимо задать параметры сервера «maxconn» и «pool-max-conn». Кроме того, если приложение не поддерживает мультиплексирование соединений, максимальное число одновременных запросов автоматически устанавливается в 1.
option keep-conn
Указывает приложению FastCGI, следует ли оставлять соединение открытым после отправки ответа.
Если параметр отключён, приложение FastCGI закрывает соединение после ответа на этот запрос. По умолчанию параметр включён.
option max-reqs <reqs>
Задаёт максимальное число одновременных запросов, которые принимает приложение.
Значение может быть переопределено, если при установке соединения получена переменная FCGI_MAX_REQS. Кроме того, если приложение не поддерживает мультиплексирование соединений, параметр игнорируется. Значение по умолчанию — 1.
option mpxs-conns
Включает или отключает поддержку мультиплексирования соединений.
Значение может быть переопределено, если при установке соединения получена переменная FCGI_MPXS_CONNS. По умолчанию параметр отключён.
set-param <name> <fmt> [ { if | unless } <condition> ]
Задаёт параметр FastCGI, который следует передать приложению. Его значение, определённое через <fmt>, должно соответствовать правилам пользовательского формата журнала (см. раздел 8.2.6
«Пользовательский формат журнала»). После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.
Эта директива позволяет переопределять значения стандартных параметров FastCGI. Если вычисленное значение является пустой строкой, правило игнорируется. Директивы выполняются в порядке объявления.
Пример:
10.1.2. Секция прокси
use-fcgi-app <name> Задаёт приложение FastCGI, используемое бэкендом.
Аргументы:
Эта директива доступна только для прокси HTTP с возможностями бэкенда и хотя бы одним сервером FastCGI. При этом серверы FastCGI можно смешивать с серверами HTTP. Однако без веской причины делать это не рекомендуется (подробности см. в разделе 10.3 об ограничениях). Для каждого бэкенда одновременно можно определить только одно приложение.
Учтите: после привязки приложения FastCGI к бэкенду, в зависимости от конфигурации, часть обработки может выполняться даже для запросов, которые не отправляются на сервер FastCGI. Правила установки параметров и передачи заголовков приложению всё равно вычисляются.
10.1.3. Пример
frontend front-http mode http bind *:80 bind *:
use_backend back-dynamic if { path_reg ^/.+\.php(/.*)?$ }
default_backend back-static
backend back-static mode http server www A.B.C.D:80
backend back-dynamic mode http use-fcgi-app php-fpm server php-fpm A.B.C.D:9000 proto fcgi
fcgi-app php-fpm log-stderr global option keep-conn
docroot /var/www/my-app
index index.php
path-info ^(/.+\.php)(/.*)?$
10.2. Параметры по умолчанию
Приложение FastCGI с ролью Responder выполняет ту же задачу, что и программа CGI/1.1. Согласно спецификации CGI/1.1 (RFC3875), скрипту необходимо передавать несколько переменных. HAProxy задаёт их, а также некоторые другие переменные, часто используемые приложениями FastCGI. Все эти переменные можно переопределить, но делать это следует осторожно.
10.3. Ограничения
В текущей реализации есть ряд ограничений. Первое связано с тем, как некоторые заголовки запроса скрываются от приложений FastCGI. Это происходит при анализе заголовков на стороне бэкенда, до установки соединения. На этом этапе HAProxy знает, что бэкенд использует приложение FastCGI, но ещё не знает, будет ли запрос направлен на сервер FastCGI. Чтобы скрыть заголовки запроса, он просто удаляет их из сообщения HTX. Поэтому, если в итоге запрос направляется на сервер HTTP, тот никогда не увидит эти заголовки. По этой причине не рекомендуется смешивать серверы FastCGI и HTTP в одном бэкенде.
Аналогично правила «set-param» и «pass-header» вычисляются при анализе заголовков запроса. То есть они выполняются всегда, даже если запрос в итоге пересылается на сервер HTTP.
При применении правила «set-param» в сообщение HTX добавляется псевдозаголовок. Поэтому, как и при переписывании заголовков HTTP, операция может завершиться неудачей при заполненном буфере. Правила «set-param» конкурируют за место с правилами «http-request».
Наконец, все параметры FastCGI и заголовки HTTP отправляются в одной записи FCGI_PARAM. Эту запись необходимо закодировать за один проход, иначе возвращается ошибка обработки. Это означает, что размер закодированной записи FCGI_PARAM не должен превышать размер буфера. Однако соблюдать резерв свободного места здесь не требуется.