独立WSGI容器¶
有用 Python 编写的流行服务器来容纳 WSGI 应用并提供 HTTP 服务。 这些服务器在运行 时是独立的:你可以从你的 web 服务器设置到它的代理。 如果你遇见问题,请注意 代理设置 一节的内容。
Gunicorn ¶
Gunicorn ‘Green Unicorn’ 是一个给 UNIX 用的 WSGI HTTP 服务器。 这是一个从 Ruby 的 Unicorn 项目移植的 pre-fork worker 模式。 它支持eventlet和greenlet。 在这个服务器上运行 Flask 应用是相当简单的:
gunicorn myproject:app
Gunicorn提供了许多命令行选项 - 参见gunicorn -h
。例如,要运行具有4个工作进程(-w 4
)的Flask应用程序绑定到localhost端口4000(-b 127.0.0.1:4000
):
gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
Gevent ¶
Gevent是一个基于协同的Python网络库,使用greenlet在libev事件循环之上提供高级同步API:
from gevent.wsgi 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
此示例将从名为myproject
的模块运行名为app
的Flask应用程序。
Twisted Web支持许多标志和选项,twistd
实用程序也是如此;见twistd -h
和twistd web
了解更多信息。例如,要在前台运行Twisted Web服务器,在端口8080上使用myproject
的应用程序:
twistd -n web --port 8080 --wsgi myproject.app
代理设置¶
如果你在一个 HTTP 代理后把你的应用部署到这些服务器中的之一,你需要重写一些标头 来让应用正常工作。 WSGI环境中的两个有问题的值通常是REMOTE_ADDR
和HTTP_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.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)
信任标头
请记住在一个非代理配置中使用这样一个中间件会是一个安全问题,因为它盲目地信任 一个可能由恶意客户端伪造的标头。
如果你想从另一个标头重写标头,你可能会使用这样的一个修正程序:
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)