FastCGI

FastCGI - это один из вариантов развёртывания приложения на таких серверах, как nginx, lighttpd и cherokee; за описанием других опций обратитесь к разделам deploying-uwsgi и deploying-wsgi-standalone. Для использования приложения WSGI с любым из этих серверов необходимо сначала настроить сервер FastCGI. Наиболее популярен flup, который будет использоваться в этом руководстве. Убедитесь в том, что установили его, Прежде чем продолжить чтение убедитесь, что он установлен.

Предварительная проверка

Удостоверьтесь, что вызовы app.run() в файле приложения находятся внутри блока if __name__ == '__main__': или вынесены в отдельный файл. Просто убедитесь в отсутствии подобных вызовов, потому что если вы решили воспользоваться FastCGI для запуска приложения, то запускать локальный сервер WSGI не нужно.

Создание файла .fcgi

Для начала нужно создать файл сервера FastCGI. Давайте назовём его yourapplication.fcgi:

#!/usr/bin/python
from flup.server.fcgi import WSGIServer
from yourapplication import app

if __name__ == '__main__':
    WSGIServer(app).run()

Этого достаточно для работы Apache, однако nginx и старые версии lighttpd требуют явного указания сокетов для связи с сервером FastCGI. Для этого нужно передать путь к сокет-файлу в WSGIServer:

WSGIServer(application, bindAddress='/path/to/fcgi.sock').run()

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

Сохраните файл yourapplication.fcgi где-нибудь, где вы сможете потом найти его. Неплохо положить его в /var/www/yourapplication или в какое-то другое подходящее место.

Убедитесь, что у этого файла установлен флаг выполнения, чтобы сервер мог его выполнить:

# chmod +x /var/www/yourapplication/yourapplication.fcgi

Настройка Apache

Приведённый выше пример достаточно хорош для того, чтобы использовать его при развёртывании с Apache, однако файл .fcgi будет встречаться в URL приложения, например: example.com/yourapplication.fcgi/news/. Есть несколько способов настройки приложения для того, чтобы убрать yourapplication.fcgi из URL. Предпочтительный способ - это использование для маршрутизации запросов серверу FastCGI директив конфигурации ScriptAlias и SetHandler. Следующий пример использует FastCgiServer для запуска 5 экземпляров приложения, которые будут обрабатывать все входящие запросы:

LoadModule fastcgi_module /usr/lib64/httpd/modules/mod_fastcgi.so

FastCgiServer /var/www/html/yourapplication/app.fcgi -idle-timeout 300 -processes 5

<VirtualHost *>
    ServerName webapp1.mydomain.com
    DocumentRoot /var/www/html/yourapplication

    AddHandler fastcgi-script fcgi
    ScriptAlias / /var/www/html/yourapplication/app.fcgi/

    <Location />
        SetHandler fastcgi-script
    </Location>
</VirtualHost>

Эти процессы будут управляться самим Apache. Если вы используете автономный сервер FastCGI, вы можете вместо этого использовать директиву FastCgiExternalServer. Заметим, что нижеуказанный путь не является реальным, он используется просто как идентификатор для других директив, таких, как as AliasMatch:

FastCgiServer /var/www/html/yourapplication -host 127.0.0.1:3000

Если задать ScriptAlias нельзя, например, на веб-узле, настроенном для нескольких пользователей, то можно воспользоваться промежуточным приложением WSGI для удаления yourapplication.fcgi из URL. Настройте .htaccess:

<IfModule mod_fcgid.c>
   AddHandler fcgid-script .fcgi
   <Files ~ (\.fcgi)>
       SetHandler fcgid-script
       Options +FollowSymLinks +ExecCGI
   </Files>
</IfModule>

<IfModule mod_rewrite.c>
   Options +FollowSymlinks
   RewriteEngine On
   RewriteBase /
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.*)$ yourapplication.fcgi/$1 [QSA,L]
</IfModule>

Теперь настроим yourapplication.fcgi:

#!/usr/bin/python
#: optional path to your local python site-packages folder
import sys
sys.path.insert(0, '<your_local_path>/lib/python2.6/site-packages')

from flup.server.fcgi import WSGIServer
from yourapplication import app

class ScriptNameStripper(object):
   def __init__(self, app):
       self.app = app

   def __call__(self, environ, start_response):
       environ['SCRIPT_NAME'] = ''
       return self.app(environ, start_response)

app = ScriptNameStripper(app)

if __name__ == '__main__':
    WSGIServer(app).run()

Настройка lighttpd

Базовая настройка FastCGI для lighttpd выглядит следующим образом:

fastcgi.server = ("/yourapplication.fcgi" =>
    ((
        "socket" => "/tmp/yourapplication-fcgi.sock",
        "bin-path" => "/var/www/yourapplication/yourapplication.fcgi",
        "check-local" => "disable",
        "max-procs" => 1
    ))
)

alias.url = (
    "/static/" => "/path/to/your/static"
)

url.rewrite-once = (
    "^(/static($|/.*))$" => "$1",
    "^(/.*)$" => "/yourapplication.fcgi$1"
)

Не забудьте включить модули FastCGI, alias и rewrite. Эта настройка закрепит приложение за /yourapplication. Если нужно, чтобы приложение работало в корне URL, понадобится обойти недоработку lighttpd при помощи промежуточного приложения LighttpdCGIRootFix.

Убедитесь, что применяете его лишь в том случае, если подключили приложение к корню URL. А также, обратитесь к документации Lighttpd за более подробной информацией сюда FastCGI and Python (отметим, что явная передача сокет-файла в run() больше не требуется).

Настройка nginx

Установка приложений FastCGI в nginx немного отличается, потому что по умолчанию программе не передаются параметры FastCGI.

Базовая конфигурация FastCGI nginx для flask выглядит следующим образом:

location = /yourapplication { rewrite ^ /yourapplication/ last; }
location /yourapplication { try_files $uri @yourapplication; }
location @yourapplication {
    include fastcgi_params;
    fastcgi_split_path_info ^(/yourapplication)(.*)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
}

Эта конфигурация привязывает приложение к /yourapplication. Привязать приложение к корню URL несколько проще, потому что не нужно думать о том, какие значения использовать в PATH_INFO и SCRIPT_NAME:

location / { try_files $uri @yourapplication; }
location @yourapplication {
    include fastcgi_params;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    fastcgi_param SCRIPT_NAME "";
    fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
}

Запуск процессов FastCGI

Поскольку Nginx и другие серверы не загружают приложения FastCGI, это нужно сделать самостоятельно. Процессами FastCGI может управлять программа Supervisor. Можно поискать другие диспетчеры процессов FastCGI или написать сценарий для запуска файла .fcgi во время загрузки, например, с помощью сценария SysV init.d. В качестве временного решения может подойти запуск сценария .fcgi из программы GNU screen. Обратитесь к странице руководства screen за более подробной информацией, однако стоит заметить, что после перезагрузки системы запуск придётся повторять вручную:

$ screen
$ /var/www/yourapplication/yourapplication.fcgi

Отладка

На большинстве веб-серверов становится всё труднее отлаживать приложения FastCGI. Довольно часто единственное, о чём сообщают журналы сервера - это о неожиданном окончании заголовков. Для отладки приложения единственное подходящее средство диагностики - это переключиться на нужного пользователя и запустить приложение вручную.

В следующем примере предполагается, что приложение называется application.fcgi, а веб-сервер работает от имени пользователя www-data:

$ su www-data
$ cd /var/www/yourapplication
$ python application.fcgi
Traceback (most recent call last):
  File "yourapplication.fcgi", line 4, in <module>
ImportError: No module named yourapplication

In this case the error seems to be «yourapplication» not being on the python path. Common problems are:

  • Relative paths being used. Don’t rely on the current working directory
  • The code depending on environment variables that are not set by the web server.
  • Different python interpreters being used.

В данном случае ошибка вызвана тем, что «yourapplication» не найден в путях поиска python. Обычно это происходит по одной из следующих причин:

  • Указаны относительные пути, которые не работают относительно текущего каталога.
  • Выполнение программы зависит от переменных окружения, которые не заданы для веб-сервера.
  • Используется интерпретатор python другой версии.

Примечания переводчика

В случае настройки Lighttpd не нужно писать никаких сценариев SysV init.d, потому что:

  1. Lighttpd может сам управлять FastCGI-процессами на локальном компьютере, самостоятельно порождая необходимое их количество (с учётом настроенного лимита),
  2. в рамках проекта Lighttpd разрабатывается собственный диспетчер процессов FastCGI - spawn-fcgi, который не настолько продвинут, чтобы регулировать количество необходимых процессов, но по крайней мере указанное количество процессов запустить и поддерживать сможет.

Обычно spawn-fcgi применяется в тех случаях, когда приложение FastCGI работает на отдельном от веб-сервера компьютере или нужно запустить приложение от имени другого пользователя, например, для изоляции друг от друга приложений разных пользователей, работающих на одном сервере. Например, так: Настройка FastCGI и PHP с индивидуальными правами пользователей.

И, наконец, никто не мешает использовать spawn-fcgi совместно с nginx.

Оригинал этой страницы