Автономные контейнеры WSGI
Существуют популярные серверы, написанные на Python, которые содержат приложения WSGI и предоставляют HTTP-сервис. Эти серверы работают автономно; к ним можно обращаться через прокси-сервер вашего веб-сервера. Обратите внимание на раздел Настройка прокси, если у вас возникнут проблемы.
Gunicorn
Gunicorn («Зелёный единорог») — это WSGI HTTP-сервер для UNIX. Он представляет собой модель pre-fork worker, перенесённую из проекта Unicorn для Ruby. Поддерживает как eventlet, так и greenlet. Запуск приложения Flask на этом сервере довольно прост:
$ gunicorn myproject:app
Gunicorn предоставляет множество опций командной строки — см. gunicorn -h. Например, для запуска приложения Flask с 4 рабочими процессами (-w
4) привязкой к локальному хосту порт 4000 (-b 127.0.0.1:4000):
$ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
Команда gunicorn ожидает имён модуля или пакета вашего приложения и экземпляра приложения внутри модуля. Если вы используете шаблон фабрики приложения, вы можете передать вызов этой фабрики:
$ gunicorn "myproject:create_app()"
uWSGI
uWSGI — это быстрый сервер приложений, написанный на C. Он очень настраивается, что делает его настройку сложнее, чем у gunicorn.
Запуск uWSGI HTTP Router:
$ uwsgi --http 127.0.0.1:5000 --module myproject:app
Для более оптимизированной настройки см. настройка uWSGI и NGINX.
Gevent
Gevent — это основанная на корутинам Python-библиотека для сетевых операций, которая использует greenlet для предоставления высокоуровневого синхронного API поверх libev цикла событий:
from gevent.pywsgi import WSGIServer
from yourapplication import app
http_server = WSGIServer(('', 5000), app)
http_server.serve_forever()
Twisted Web
Twisted Web — это веб-сервер, поставляемый с Twisted, зрелой, неблокирующей, управляемой событиями библиотекой сетевых операций. Twisted Web поставляется со стандартным контейнером WSGI, которым можно управлять из командной строки с помощью утилиты twistd:
$ twistd web --wsgi myproject.app
Этот пример запустит приложение Flask под названием app из модуля под названием myproject.
Twisted Web поддерживает множество флагов и опций, и утилита twistd также; см. twistd -h и twistd web -h для получения дополнительной информации. Например, для запуска сервера Twisted Web в фоновом режиме на порту 8080 с приложением из myproject:
$ twistd -n web --port tcp:8080 --wsgi myproject.app
Настройка прокси
Если вы развертываете приложение с помощью одного из этих серверов за HTTP-прокси, вам необходимо переписать несколько заголовков для корректной работы приложения. Обычно двумя проблемными значениями в среде WSGI являются REMOTE_ADDR и HTTP_HOST. Вы можете настроить ваш httpd для передачи этих заголовков или исправить их в middleware. Werkzeug поставляет исправитель, который решит некоторые распространённые настройки, но вы можете захотеть написать собственный WSGI middleware для конкретных настроек.
Вот простая настройка nginx, которая проксирует приложение, предоставляемое на localhost на порту 8000, устанавливая соответствующие заголовки:
server {
listen 80;
server_name _;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
proxy_pass http://127.0.0.1:8000/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Если ваш httpd не предоставляет эти заголовки, наиболее распространённая настройка подразумевает, что хост устанавливается из X-Forwarded-Host, а удалённый адрес — из X-Forwarded-For:
from werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
Доверие к заголовкам
Пожалуйста, имейте в виду, что использование такого middleware вне прокси-настроек является проблемой безопасности, так как оно слепо доверяет входящим заголовкам, которые могут быть подделаны злонамеренными клиентами.
Если вы хотите переписать заголовки из другого заголовка, вы можете использовать исправитель, подобный этому:
class CustomProxyFix(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
host = environ.get('HTTP_X_FHOST', '')
if host:
environ['HTTP_HOST'] = host
return self.app(environ, start_response)
app.wsgi_app = CustomProxyFix(app.wsgi_app)
© 2007–2021 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.0.x/deploying/wsgi-standalone/