使用 mongodb 的 Flask/uWSGI/nginx 应用超时
Timeout with Flask/uWSGI/nginx app using mongodb
我在 uWSGI/nginx 上有一个 Flask python 网络应用程序运行良好,除非我使用 pymongo
,特别是当我初始化 MongoClient class 时。当我在使用 pymongo 时尝试访问应用程序时出现以下 nginx 错误:
019/02/19 21:58:13 [error] 16699#0: *5 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 127.0.0.1, server: example.com, request: "GET /api/test HTTP/1.1", upstream: "uwsgi://unix:/var/www/html/myapp/myapp.sock:”, host: “example.com”
我的小测试应用程序:
from flask import Flask
from flask_cors import CORS
from bson.json_util import dumps
import pymongo
DEBUG = True
app = Flask(__name__)
app.config.from_object(__name__)
CORS(app)
client = pymongo.MongoClient() # This line
db = client.myapp
@app.route('/api/test')
def test():
item = db.items.find_one()
return item['name']
def create_app(app_name='MYAPP'):
return app
# if __name__ == '__main__':
# app.run(debug=True, threaded=True, host='0.0.0.0')
如果我从命令行 运行 这个应用程序 (python app.py
) 它可以正常访问 0.0.0.0:5000/api/test
,所以我很确定这只是一个 uWSGI 配置问题。我的第一个想法是在我的 nginx 配置文件中增加 uwsgi_read_timeout
参数:
uwsgi_read_timeout 3600
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
location /api {
include uwsgi_params;
uwsgi_read_timeout 3600;
uwsgi_pass unix:/var/www/html/myapp/myapp.sock;
}
location / {
root /var/www/html/myapp;
try_files $uri $uri/ /index.html;
}
#return 301 https://$server_name$request_uri;
}
但是没有明显的效果。我的 uWSGI 应用程序 运行ning 作为服务,使用以下配置 (myapp.ini):
[uwsgi]
module = wsgi:app
master = true
processes = 4
enable-threads = True
socket = /var/www/html/myapp/myapp.sock
chmod-socket = 660
vacuum = true
die-on-term = true
同样,除了我尝试初始化 pymongo 时,一切似乎都运行良好。最后,我的应用程序的服务文件:
[Unit]
Description=uWSGI Python container server
After=network.target
[Service]
User=pi
Group=www-data
WorkingDirectory=/var/www/html/myapp
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/myapp.ini
[Install]
WantedBy=multi-user.target
我认为问题在于您正在分叉,这会导致 PyMongo 出现问题。
PyMongo 是线程安全的,但不是 Fork 安全的。一旦你 运行 应用程序处于守护进程模式,你就在分叉进程。您必须在应用程序中创建一个 MongoClient,以便您的线程可以在进程启动后看到它。
你可以试试这个(我没试过,我通常把这样的东西包装在 class 中,然后在 init 方法中执行):
def create_app(app_name='MYAPP'):
app.client = pymongo.MongoClient(connect=False) # this will prevent connecting until you need it.
app.db = app.client.myapp
return app
我在 uWSGI/nginx 上有一个 Flask python 网络应用程序运行良好,除非我使用 pymongo
,特别是当我初始化 MongoClient class 时。当我在使用 pymongo 时尝试访问应用程序时出现以下 nginx 错误:
019/02/19 21:58:13 [error] 16699#0: *5 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 127.0.0.1, server: example.com, request: "GET /api/test HTTP/1.1", upstream: "uwsgi://unix:/var/www/html/myapp/myapp.sock:”, host: “example.com”
我的小测试应用程序:
from flask import Flask
from flask_cors import CORS
from bson.json_util import dumps
import pymongo
DEBUG = True
app = Flask(__name__)
app.config.from_object(__name__)
CORS(app)
client = pymongo.MongoClient() # This line
db = client.myapp
@app.route('/api/test')
def test():
item = db.items.find_one()
return item['name']
def create_app(app_name='MYAPP'):
return app
# if __name__ == '__main__':
# app.run(debug=True, threaded=True, host='0.0.0.0')
如果我从命令行 运行 这个应用程序 (python app.py
) 它可以正常访问 0.0.0.0:5000/api/test
,所以我很确定这只是一个 uWSGI 配置问题。我的第一个想法是在我的 nginx 配置文件中增加 uwsgi_read_timeout
参数:
uwsgi_read_timeout 3600
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
location /api {
include uwsgi_params;
uwsgi_read_timeout 3600;
uwsgi_pass unix:/var/www/html/myapp/myapp.sock;
}
location / {
root /var/www/html/myapp;
try_files $uri $uri/ /index.html;
}
#return 301 https://$server_name$request_uri;
}
但是没有明显的效果。我的 uWSGI 应用程序 运行ning 作为服务,使用以下配置 (myapp.ini):
[uwsgi]
module = wsgi:app
master = true
processes = 4
enable-threads = True
socket = /var/www/html/myapp/myapp.sock
chmod-socket = 660
vacuum = true
die-on-term = true
同样,除了我尝试初始化 pymongo 时,一切似乎都运行良好。最后,我的应用程序的服务文件:
[Unit]
Description=uWSGI Python container server
After=network.target
[Service]
User=pi
Group=www-data
WorkingDirectory=/var/www/html/myapp
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/myapp.ini
[Install]
WantedBy=multi-user.target
我认为问题在于您正在分叉,这会导致 PyMongo 出现问题。
PyMongo 是线程安全的,但不是 Fork 安全的。一旦你 运行 应用程序处于守护进程模式,你就在分叉进程。您必须在应用程序中创建一个 MongoClient,以便您的线程可以在进程启动后看到它。
你可以试试这个(我没试过,我通常把这样的东西包装在 class 中,然后在 init 方法中执行):
def create_app(app_name='MYAPP'):
app.client = pymongo.MongoClient(connect=False) # this will prevent connecting until you need it.
app.db = app.client.myapp
return app