• en
  • Language: ru
  • Documentation version: 1.1.x

FastCGI

FastCGI - это вариант развертывания на таких серверах, как nginx, lighttpd и cherokee; другие варианты см. в uWSGI и Автономные контейнеры WSGI. Чтобы использовать ваше WSGI-приложение с любым из них, вам сначала понадобится сервер FastCGI. Наиболее популярным из них является flup, который мы будем использовать в этом руководстве. Убедитесь в том, что он установлен, чтобы следовать дальше.

Осторожно

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

Создание файла .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. Предпочтительным способом является использование конфигурационных директив ScriptAlias и SetHandler для маршрутизации запросов к серверу FastCGI. В следующем примере 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. Обратите внимание, что в приведенном ниже примере путь не является реальным, он просто используется в качестве идентификатора для других директив, таких как 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/python<your_python_version>/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. Также смотрите документацию Lighty для получения дополнительной информации о FastCGI and Python (обратите внимание, что явная передача сокета в run() больше не нужна).

Настройка nginx

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

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

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-приложения, вам придется сделать это самостоятельно. Supervisor can manage FastCGI processes. Вы можете поискать другие менеджеры процессов FastCGI или написать сценарий для запуска вашего файла .fcgi“ при загрузке, например, используя сценарий SysV ``init.d`. В качестве временного решения вы всегда можете запустить сценарий .fcgi внутри GNU screen. Смотрите man 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

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

  • Используются относительные пути. Не полагайтесь на текущий рабочий каталог.

  • Код, зависящий от переменных окружения, которые не установлены веб-сервером.

  • Используются разные интерпретаторы python.