使用 mongodb 的 Flask/uWSGI/nginx 应用程序超时

Rya*_*ski 6 python nginx flask uwsgi raspberry-pi

我在 uWSGI/nginx 上有一个 Flask python Web 应用程序,工作正常,除了当我使用 时pymongo,特别是当我初始化 MongoClient 类时。当我尝试使用 pymongo 访问应用程序时,出现以下 nginx 错误:

\n\n
\n

019/02/19 21:58:13 [错误] 16699#0: *5 recv() 失败 (104: 连接被对等方重置) 从上游读取响应头,客户端:127.0.0.1,服务器:example.com,请求:“GET /api/test HTTP/1.1”,上游:“uwsgi://unix:/var/www/html/myapp/myapp.sock:\xe2\x80\x9d,主机:\xe2\x80\x9cexample .com\xe2\x80\x9d

\n
\n\n

我的小测试应用程序:

\n\n
from flask import Flask\nfrom flask_cors import CORS\nfrom bson.json_util import dumps\nimport pymongo\n\nDEBUG = True\napp = Flask(__name__)\napp.config.from_object(__name__)\nCORS(app)\n\nclient = pymongo.MongoClient() # This line\ndb = client.myapp\n\n@app.route(\'/api/test\')\ndef test():\n    item = db.items.find_one()\n    return item[\'name\']\n\ndef create_app(app_name=\'MYAPP\'):\n    return app\n\n# if __name__ == \'__main__\':\n#   app.run(debug=True, threaded=True, host=\'0.0.0.0\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我从命令行 ( python app.py) 运行这个应用程序,它可以正常访问0.0.0.0:5000/api/test,所以我很确定这只是一个 uWSGI 配置问题。我的第一个想法是增加uwsgi_read_timeoutnginx 配置文件中的参数:

\n\n
\n

uwsgi_read_timeout 3600

\n
\n\n
server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n\n    server_name example.com www.example.com;\n\n    location /api {\n        include uwsgi_params;\n        uwsgi_read_timeout 3600;\n        uwsgi_pass unix:/var/www/html/myapp/myapp.sock;\n    }\n\n    location / {\n      root /var/www/html/myapp;\n      try_files $uri $uri/ /index.html;\n    }\n\n    #return 301 https://$server_name$request_uri;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但并没有明显的效果。我的 uWSGI 应用程序作为服务运行,使用以下配置(myapp.ini):

\n\n
[uwsgi]\nmodule = wsgi:app\n\nmaster = true\nprocesses = 4\nenable-threads = True\n\nsocket = /var/www/html/myapp/myapp.sock\nchmod-socket = 660\nvacuum = true\n\ndie-on-term = true\n
Run Code Online (Sandbox Code Playgroud)\n\n

同样,除了当我尝试初始化 pymongo 时,一切似乎都工作正常。最后,我的应用程序的服务文件:

\n\n
[Unit]\nDescription=uWSGI Python container server\nAfter=network.target\n\n[Service]\nUser=pi\nGroup=www-data\nWorkingDirectory=/var/www/html/myapp\nExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/myapp.ini\n\n[Install]\nWantedBy=multi-user.target\n
Run Code Online (Sandbox Code Playgroud)\n

小智 5

我认为问题在于您正在分叉,这会导致 PyMongo 出现问题。

PyMongo 是线程安全的,但不是 Fork 安全的。一旦您以守护进程模式运行应用程序,您就会分叉该进程。您必须在应用程序内创建一个 MongoClient,以便您的线程可以在进程启动后看到它。

你可以尝试这个(我没有尝试这个,我通常将这样的东西包装在一个类中并在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
Run Code Online (Sandbox Code Playgroud)

阅读此内容: http: //api.mongodb.com/python/current/faq.html#id3