Перейти к содержанию

10. Приложения FastCGI

Настройка приложений 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>

fcgi-app <name>

Объявляет приложение FastCGI с именем <name>. Для корректной конфигурации необходимо определить как минимум корневой каталог документов.

acl <aclname> <criterion> [flags] [operator] <value> ...

acl <aclname> <criterion> [flags] [operator] <value> ...

Объявляет или дополняет список контроля доступа.

Подробности см. в описании директивы «acl» в разделе 4.2 и в разделе 7 об использовании ACL. Списки ACL, определённые для приложения FastCGI, доступны только ему. Их нельзя использовать в другом приложении или прокси. Аналогично приложение FastCGI не может использовать списки ACL, определённые в других секциях. Однако предопределённые ACL доступны.

docroot <path>

docroot <path>

Задаёт корневой каталог документов на удалённом узле. <path> используется для формирования значений по умолчанию параметров FastCGI SCRIPT_FILENAME и PATH_TRANSLATED. Это обязательная настройка.

index <script-name>

index <script-name>

Задаёт имя скрипта, добавляемое к URI, оканчивающемуся косой чертой («/»), чтобы получить значение по умолчанию параметра FastCGI SCRIPT_NAME. Это необязательная настройка.

Пример:

index index.php

log-stderr global

log-stderr global
log-stderr <target> [len <length>] [format <format>]
    [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]

Включает запись в журнал сообщений STDERR, выдаваемых приложением FastCGI.

Подробности см. в описании директивы «log» в разделе 4.2 . Это необязательная настройка. По умолчанию сообщения STDERR игнорируются.

pass-header <name> [ { if | unless } <condition> ]

pass-header <name> [ { if | unless } <condition> ]

Задаёт имя заголовка запроса, передаваемого приложению FastCGI. После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.

Большинство заголовков запроса уже доступны приложению FastCGI с префиксом «HTTP_». Поэтому эта директива нужна только для передачи заголовков, которые намеренно исключаются. Сейчас исключаются заголовки «Authorization», «Proxy-Authorization» и заголовки, действующие только на одном участке соединения (hop-by-hop).

Обратите внимание: заголовки «Content-type» и «Content-length» никогда не передаются приложению FastCGI, поскольку уже преобразованы в параметры.

path-info <regex>

path-info <regex>

Задаёт регулярное выражение для извлечения script-name и path-info из пути после декодирования URL. <regex> может содержать две группы захвата: первая извлекает имя скрипта, вторая — path-info. Первая обязательна, вторая необязательна. Таким образом можно извлечь script-name из пути, игнорируя path-info. Это необязательная настройка. Если она не задана, сопоставление пути не выполняется, а параметры FastCGI PATH_INFO и PATH_TRANSLATED не заполняются.

Из соображений безопасности при заданном регулярном выражении в пути после декодирования URL запрещены символы перевода строки и нулевые символы. Ограничение связано с тем, что иначе сопоставление всегда завершается неудачей (из-за особенностей выполнения регулярных выражений в HAProxy). Поэтому, если после декодирования URL в пути обнаружен любой из этих двух символов, клиенту возвращается ошибка. Здесь применяется принцип наименьшего удивления.

Пример:

path-info ^(/.+\.php)(/.*)?$ # both script-name and path-info may be set
path-info ^(/.+\.php)        # the path-info is ignored

option get-values

option get-values
no 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

option keep-conn
no option keep-conn

Указывает приложению FastCGI, следует ли оставлять соединение открытым после отправки ответа.

Если параметр отключён, приложение FastCGI закрывает соединение после ответа на этот запрос. По умолчанию параметр включён.

option max-reqs <reqs>

option max-reqs <reqs>

Задаёт максимальное число одновременных запросов, которые принимает приложение.

Значение может быть переопределено, если при установке соединения получена переменная FCGI_MAX_REQS. Кроме того, если приложение не поддерживает мультиплексирование соединений, параметр игнорируется. Значение по умолчанию — 1.

option mpxs-conns

option mpxs-conns
no option mpxs-conns

Включает или отключает поддержку мультиплексирования соединений.

Значение может быть переопределено, если при установке соединения получена переменная FCGI_MPXS_CONNS. По умолчанию параметр отключён.

set-param <name> <fmt> [ { if | unless } <condition> ]

set-param <name> <fmt> [ { if | unless } <condition> ]

Задаёт параметр FastCGI, который следует передать приложению. Его значение, определённое через <fmt>, должно соответствовать правилам пользовательского формата журнала (см. раздел 8.2.6 «Пользовательский формат журнала»). После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.

Эта директива позволяет переопределять значения стандартных параметров FastCGI. Если вычисленное значение является пустой строкой, правило игнорируется. Директивы выполняются в порядке объявления.

Пример:

# PHP only, required if PHP was built with --enable-force-cgi-redirect
set-param REDIRECT_STATUS 200

set-param PHP_AUTH_DIGEST %[req.hdr(Authorization)]

10.1.2. Секция прокси

use-fcgi-app <name> Задаёт приложение FastCGI, используемое бэкендом.

Аргументы:

<name>    is the name of the FastCGI application to use.

Эта директива доступна только для прокси 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 ^/.+&#92;.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 ^(/.+&#92;.php)(/.*)?$

10.2. Параметры по умолчанию

Приложение FastCGI с ролью Responder выполняет ту же задачу, что и программа CGI/1.1. Согласно спецификации CGI/1.1 (RFC3875), скрипту необходимо передавать несколько переменных. HAProxy задаёт их, а также некоторые другие переменные, часто используемые приложениями FastCGI. Все эти переменные можно переопределить, но делать это следует осторожно.

  +-------------------+-----------------------------------------------------+
  | AUTH_TYPE         | Identifies the mechanism, if any, used by HAProxy   |
  |                   | to authenticate the user. Concretely, only the      |
  |                   | BASIC authentication mechanism is supported.        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | CONTENT_LENGTH    | Contains the size of the message-body attached to   |
  |                   | the request. It means only requests with a known    |
  |                   | size are considered as valid and sent to the        |
  |                   | application.                                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | CONTENT_TYPE      | Contains the type of the message-body attached to   |
  |                   | the request. It may not be set.                     |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | DOCUMENT_ROOT     | Contains the document root on the remote host under |
  |                   | which the script should be executed, as defined in  |
  |                   | the application's configuration.                    |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | GATEWAY_INTERFACE | Contains the dialect of CGI being used by HAProxy   |
  |                   | to communicate with the FastCGI application.        |
  |                   | Concretely, it is set to "CGI/1.1".                 |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | PATH_INFO         | Contains the portion of the URI path hierarchy      |
  |                   | following the part that identifies the script       |
  |                   | itself. To be set, the directive "path-info" must   |
  |                   | be defined.                                         |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | PATH_TRANSLATED   | If PATH_INFO is set, it is its translated version.  |
  |                   | It is the concatenation of DOCUMENT_ROOT and        |
  |                   | PATH_INFO. If PATH_INFO is not set, this parameters |
  |                   | is not set too.                                     |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | QUERY_STRING      | Contains the request's query string. It may not be  |
  |                   | set.                                                |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REMOTE_ADDR       | Contains the network address of the client sending  |
  |                   | the request.                                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REMOTE_USER       | Contains the user identification string supplied by |
  |                   | client as part of user authentication.              |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REQUEST_METHOD    | Contains the method which should be used by the     |
  |                   | script to process the request.                      |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REQUEST_URI       | Contains the request's URI.                         |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SCRIPT_FILENAME   | Contains the absolute pathname of the script. it is |
  |                   | the concatenation of DOCUMENT_ROOT and SCRIPT_NAME. |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SCRIPT_NAME       | Contains the name of the script. If the directive   |
  |                   | "path-info" is defined, it is the first part of the |
  |                   | URI path hierarchy, ending with the script name.    |
  |                   | Otherwise, it is the entire URI path.               |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_NAME       | Contains the name of the server host to which the   |
  |                   | client request is directed. It is the value of the  |
  |                   | header "Host", if defined. Otherwise, the           |
  |                   | destination address of the connection on the client |
  |                   | side.                                               |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_PORT       | Contains the destination TCP port of the connection |
  |                   | on the client side, which is the port the client    |
  |                   | connected to.                                       |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_PROTOCOL   | Contains the request's protocol.                    |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_SOFTWARE   | Contains the string "HAProxy" followed by the       |
  |                   | current HAProxy version.                            |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | HTTPS             | Set to a non-empty value ("on") if the script was   |
  |                   | queried through the HTTPS protocol.                 |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+

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 не должен превышать размер буфера. Однако соблюдать резерв свободного места здесь не требуется.