6

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. I get the following nginx error when I try to access the app while using pymongo:

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”

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. My first thought was to increase the uwsgi_read_timeout parameter in my nginx config file:

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] 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. 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 

1 Answer 1

5

I believe the issue is that you're forking and this causes issues with PyMongo.

PyMongo is thread safe but not Fork safe. 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.

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

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.