独立的 WSGI 容器 — Flask 文档

来自菜鸟教程
Flask/docs/1.1.x/deploying/wsgi-standalone
跳转至:导航、​搜索

独立的 WSGI 容器

有一些用 Python 编写的流行服务器,它们包含 WSGI 应用程序并提供 HTTP 服务。 这些服务器在运行时是独立的; 您可以从您的网络服务器代理到他们。 如果遇到问题,请注意有关 代理设置 的部分。

独角兽

Gunicorn 'Green Unicorn' 是 UNIX 的 WSGI HTTP 服务器。 这是一个从 Ruby 的 Unicorn 项目移植过来的 pre-fork worker 模型。 它支持 eventletgreenlet。 在此服务器上运行 Flask 应用程序非常简单:

$ gunicorn myproject:app

Gunicorn 提供了许多命令行选项——参见 gunicorn -h。 例如,要运行具有 4 个工作进程 (-w 4) 绑定到本地主机端口 4000 (-b 127.0.0.1:4000) 的 Flask 应用程序:

$ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app

gunicorn 命令需要您的应用程序模块或包的名称以及模块内的应用程序实例。 如果您使用应用程序工厂模式,则可以将调用传递给:

$ gunicorn "myproject:create_app()"

uWSGI

uWSGI 是一个用 C 编写的快速应用服务器。 它是非常可配置的,这使得设置比 gunicorn 更复杂。

运行 uWSGI HTTP 路由器

$ uwsgi --http 127.0.0.1:5000 --module myproject:app

有关更优化的设置,请参阅 配置 uWSGI 和 NGINX


万事达

Gevent 是一个基于协程的 Python 网络库,它使用 greenletlibev 事件循环之上提供高级同步 API:

from gevent.pywsgi import WSGIServer
from yourapplication import app

http_server = WSGIServer(('', 5000), app)
http_server.serve_forever()

扭曲的网络

Twisted WebTwisted 附带的 Web 服务器,这是一个成熟的、非阻塞的事件驱动网络库。 Twisted Web 带有一个标准的 WSGI 容器,可以使用 twistd 实用程序从命令行进行控制:

$ twistd web --wsgi myproject.app

此示例将从名为 myproject 的模块运行名为 app 的 Flask 应用程序。

Twisted Web 支持许多标志和选项,twistd 实用程序也支持; 有关详细信息,请参阅 twistd -htwistd web -h。 例如,要在前台运行 Twisted Web 服务器,在端口 8080 上,使用来自 myproject 的应用程序:

$ twistd -n web --port tcp:8080 --wsgi myproject.app

代理设置

如果您使用 HTTP 代理后面的这些服务器之一部署您的应用程序,您将需要重写一些标头才能使应用程序正常工作。 WSGI 环境中的两个有问题的值通常是 REMOTE_ADDRHTTP_HOST。 您可以配置 httpd 以传递这些标头,也可以在中间件中修复它们。 Werkzeug 提供了一个修复程序来解决一些常见的设置,但您可能想为特定设置编写自己的 WSGI 中间件。

这是一个简单的 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)

信任标头

请记住,在非代理设置中使用这样的中间件是一个安全问题,因为它会盲目信任可能由恶意客户端伪造的传入标头。


如果您想从另一个标头重写标头,您可能需要使用这样的固定器:

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)