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

时间:2019-02-20 03:14:00

标签: python nginx flask raspberry-pi uwsgi

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

  

019/02/19 21:58:13 [错误] 16699#0:* 5 recv()失败(104:对等方重置连接),同时从上游读取响应头,客户端:127.0.0.1,服务器:示例.com,请求:“ GET / api / test HTTP / 1.1”,上游:“ uwsgi:// unix:/var/www/html/myapp/myapp.sock:”,主机:“ 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应用程序使用以下配置(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

1 个答案:

答案 0 :(得分:1)

我相信问题是您在分叉,这会导致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

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