简体   繁体   English

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

[英]Timeout with Flask/uWSGI/nginx app using mongodb

I have a Flask python web app on uWSGI/nginx that works fine, except when I use pymongo , specifically when I initialize the MongoClient class. 我在uWSGI / nginx上有一个Flask python网络应用程序,除了我使用pymongo ,特别是在初始化MongoClient类时,都可以正常工作。 I get the following nginx error when I try to access the app while using pymongo: 当我尝试使用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” 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:”,主机:“ example.com”

My small test app: 我的小型测试应用程序:

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')

If I run this app from the command line ( python app.py ) it works fine accessing 0.0.0.0:5000/api/test , so I'm pretty sure it's just a uWSGI configuration issue. 如果我从命令行( python app.py )运行此应用程序,则可以很好地访问0.0.0.0:5000/api/test ,因此我很确定这只是一个uWSGI配置问题。 My first thought was to increase the uwsgi_read_timeout parameter in my nginx config file: 我的第一个想法是在我的nginx配置文件中增加uwsgi_read_timeout参数:

uwsgi_read_timeout 3600 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;
}

But it had no apparent effect. 但这并没有明显的效果。 My uWSGI app is running as a service, using the following config (myapp.ini): 我的uWSGI应用程序使用以下配置(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

Again, everything seems to work fine except for when I try to initialize pymongo. 同样,除了我尝试初始化pymongo之外,其他一切似乎都可以正常工作。 Finally, my app's service file: 最后,我的应用程序的服务文件:

[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

I believe the issue is that you're forking and this causes issues with PyMongo. 我相信问题是您在分叉,这会导致PyMongo出现问题。

PyMongo is thread safe but not Fork safe. PyMongo是线程安全的,但不是Fork安全的。 Once you run the app in daemon mode you are forking the process. 在守护程序模式下运行该应用程序后,便会分叉该过程。 You'll have to create a MongoClient inside the app so that your threads can see it after the process has started. 您必须在应用程序内部创建一个MongoClient,以便您的线程可以在该过程开始后看到它。

You can try this(I didn't try this out, I normally wrap stuff like this in a class and do this in the init method): 您可以尝试一下(我没有尝试过,我通常将这样的东西包装在一个类中,并在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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM