带有 gaiohttp worker 的 gunicorn 总是用 flask app 返回 404
gunicorn with gaiohttp worker always returning 404 with flask app
我是 运行 一个在 nginx 代理后面使用 gunicorn 的 flask 应用程序,我正在尝试让 gaiohttp worker 工作。 The app just returns 404 for all URLS when the gaiohttp worker is selected
当使用 sync 或 gevent worker 时,一切正常。也不要 运行 直接连接到 gunicorn 和 gaiohttp 即不使用 nginx 它工作正常。
我已经阅读了我能找到的所有内容。
我错过了什么吗? 运行 在 nginx 代理后面时 gaiohttp worker 是否有效?
我的 nginx 配置:
location /app {
proxy_pass http://127.0.0.1:9002;
rewrite /app(.*) / break;
proxy_redirect off;
proxy_buffering on;
proxy_pass_header Server;
proxy_set_header X-Scheme $scheme;
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-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Script-Name /app;
}
独角兽:
/usr/bin/gunicorn --workers 2 -k gaiohttp -b 127.0.0.1:9002 app:app
使用最新版本的 gunicorn 等等
我设法解决了这个问题。
此处的行导致了 nginx 配置中的问题:
rewrite /app(.*) / break;
我的 Flask 应用程序中需要一个代理中间件来正确处理反向代理。
class ReverseProxied(object):
'''Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is
different than what is used locally.
In nginx:
location /myprefix {
proxy_pass http://192.168.0.1:5001;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /myprefix;
}
:param app: the WSGI application
'''
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
if script_name:
server = environ.get('HTTP_X_FORWARDED_SERVER', '')
if server:
environ['HTTP_HOST'] = server
environ['SCRIPT_NAME'] = script_name
path_info = environ['PATH_INFO']
if path_info.startswith(script_name):
environ['PATH_INFO'] = path_info[len(script_name):]
scheme = environ.get('HTTP_X_SCHEME', '')
if scheme:
environ['wsgi.url_scheme'] = scheme
return self.app(environ, start_response)
在应用的 __init__.py
中:app.wsgi_app = ReverseProxied(app.wsgi_app)
另一种解决方案是为所有 Flask 路由添加前缀。
子安装在另一个 WSGI 容器内
假设您要在 WSGI 容器(mod_wsgi、uwsgi、gunicorn 等)中 运行 这个应用程序;您实际上需要 在那个前缀 处挂载应用程序作为该 WSGI 容器的子部分(任何会说 WSGI 的东西)并将您的 APPLICATION_ROOT
配置值设置为你的前缀:
app.config["APPLICATION_ROOT"] = "/app"
@app.route("/")
def index():
return "The URL for this page is {}".format(url_for("index"))
# Will return "The URL for this page is /app"
设置 APPLICATION_ROOT
配置值只是将 Flask 的会话 cookie 限制为该 URL 前缀。 Flask 和 Werkzeug 出色的 WSGI 处理能力将自动为您处理其他一切。
正确安装您的应用程序的示例
如果您不确定第一段的含义,请看一下这个安装了 Flask 的示例应用程序:
from flask import Flask, url_for
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware
app = Flask(__name__)
app.config['APPLICATION_ROOT'] = '/app'
@app.route('/')
def index():
return 'The URL for this page is {}'.format(url_for('index'))
def simple(env, resp):
resp(b'200 OK', [(b'Content-Type', b'text/plain')])
return [b'Hello WSGI World']
app.wsgi_app = DispatcherMiddleware(simple, {'/app': app.wsgi_app})
if __name__ == '__main__':
app.run('localhost', 5000)
代理对应用程序的请求
另一方面,如果您将 运行将您的 Flask 应用程序置于其 WSGI 容器的根目录并代理对它的请求(例如,如果它正在使用 FastCGI,或者如果nginx 正在 proxy_pass
-ing 向您的独立 uwsgi
/ gevent
服务器请求子端点,然后您可以:
- 使用蓝图,正如 Miguel 在 his answer 中指出的那样。
- 或使用
werkzeug
中的DispatcherMiddleware
(或su27's answer中的PrefixMiddleware
)来挂载你的应用程序在您使用的独立 WSGI 服务器中。 (有关要使用的代码,请参阅上面的 正确安装您的应用程序 的示例)。
我是 运行 一个在 nginx 代理后面使用 gunicorn 的 flask 应用程序,我正在尝试让 gaiohttp worker 工作。 The app just returns 404 for all URLS when the gaiohttp worker is selected
当使用 sync 或 gevent worker 时,一切正常。也不要 运行 直接连接到 gunicorn 和 gaiohttp 即不使用 nginx 它工作正常。
我已经阅读了我能找到的所有内容。
我错过了什么吗? 运行 在 nginx 代理后面时 gaiohttp worker 是否有效?
我的 nginx 配置:
location /app {
proxy_pass http://127.0.0.1:9002;
rewrite /app(.*) / break;
proxy_redirect off;
proxy_buffering on;
proxy_pass_header Server;
proxy_set_header X-Scheme $scheme;
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-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Script-Name /app;
}
独角兽:
/usr/bin/gunicorn --workers 2 -k gaiohttp -b 127.0.0.1:9002 app:app
使用最新版本的 gunicorn 等等
我设法解决了这个问题。
此处的行导致了 nginx 配置中的问题:
rewrite /app(.*) / break;
我的 Flask 应用程序中需要一个代理中间件来正确处理反向代理。
class ReverseProxied(object):
'''Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is
different than what is used locally.
In nginx:
location /myprefix {
proxy_pass http://192.168.0.1:5001;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /myprefix;
}
:param app: the WSGI application
'''
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
if script_name:
server = environ.get('HTTP_X_FORWARDED_SERVER', '')
if server:
environ['HTTP_HOST'] = server
environ['SCRIPT_NAME'] = script_name
path_info = environ['PATH_INFO']
if path_info.startswith(script_name):
environ['PATH_INFO'] = path_info[len(script_name):]
scheme = environ.get('HTTP_X_SCHEME', '')
if scheme:
environ['wsgi.url_scheme'] = scheme
return self.app(environ, start_response)
在应用的 __init__.py
中:app.wsgi_app = ReverseProxied(app.wsgi_app)
另一种解决方案是为所有 Flask 路由添加前缀。
子安装在另一个 WSGI 容器内
假设您要在 WSGI 容器(mod_wsgi、uwsgi、gunicorn 等)中 运行 这个应用程序;您实际上需要 在那个前缀 处挂载应用程序作为该 WSGI 容器的子部分(任何会说 WSGI 的东西)并将您的 APPLICATION_ROOT
配置值设置为你的前缀:
app.config["APPLICATION_ROOT"] = "/app"
@app.route("/")
def index():
return "The URL for this page is {}".format(url_for("index"))
# Will return "The URL for this page is /app"
设置 APPLICATION_ROOT
配置值只是将 Flask 的会话 cookie 限制为该 URL 前缀。 Flask 和 Werkzeug 出色的 WSGI 处理能力将自动为您处理其他一切。
正确安装您的应用程序的示例
如果您不确定第一段的含义,请看一下这个安装了 Flask 的示例应用程序:
from flask import Flask, url_for
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware
app = Flask(__name__)
app.config['APPLICATION_ROOT'] = '/app'
@app.route('/')
def index():
return 'The URL for this page is {}'.format(url_for('index'))
def simple(env, resp):
resp(b'200 OK', [(b'Content-Type', b'text/plain')])
return [b'Hello WSGI World']
app.wsgi_app = DispatcherMiddleware(simple, {'/app': app.wsgi_app})
if __name__ == '__main__':
app.run('localhost', 5000)
代理对应用程序的请求
另一方面,如果您将 运行将您的 Flask 应用程序置于其 WSGI 容器的根目录并代理对它的请求(例如,如果它正在使用 FastCGI,或者如果nginx 正在 proxy_pass
-ing 向您的独立 uwsgi
/ gevent
服务器请求子端点,然后您可以:
- 使用蓝图,正如 Miguel 在 his answer 中指出的那样。
- 或使用
werkzeug
中的DispatcherMiddleware
(或su27's answer中的PrefixMiddleware
)来挂载你的应用程序在您使用的独立 WSGI 服务器中。 (有关要使用的代码,请参阅上面的 正确安装您的应用程序 的示例)。