Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gunicorn+flask+pymongo+gevent hangs on initialization

Simple test app:

from gevent import monkey
monkey.patch_all()

from pymongo import Connection, MongoClient
from flask import Flask, make_response

app = Flask(__name__)
print "connect"
connection = MongoClient("host1, host2, host3", 27017, max_pool_size=4, **{"connectTimeoutMS": 3000, "socketTimeoutMS": 3000, "use_greenlets": True})
print "db"
db = connection.barn_2

@app.route('/')
def hello_world():
    return make_response("Hello world!", 200, {'Content-type': 'application/json; charset=UTF-8'})

if __name__ == '__main__':
    app.run()

Works perfectly if it's run as a standalone app:

shcheklein@hostname:~$ python test.py
connect
db
 * Running on http://127.0.0.1:5000/
127.0.0.1 - - [07/Apr/2014 13:07:31] "GET / HTTP/1.1" 200 -
^CKeyboardInterrupt

But fails to start with gunicorn:

shcheklein@hostname:~$ gunicorn -w 1 -k gevent -t 5 --debug test:app
2014-04-07 13:15:04 [9752] [INFO] Starting gunicorn 18.0
2014-04-07 13:15:04 [9752] [INFO] Listening at: http://127.0.0.1:8000 (9752)
2014-04-07 13:15:04 [9752] [INFO] Using worker: gevent
2014-04-07 13:15:04 [9757] [INFO] Booting worker with pid: 9757
connect
2014-04-07 13:15:09 [9752] [CRITICAL] WORKER TIMEOUT (pid:9757)
2014-04-07 13:15:09 [9752] [CRITICAL] WORKER TIMEOUT (pid:9757)
2014-04-07 13:15:10 [9787] [INFO] Booting worker with pid: 9787
connect
2014-04-07 13:15:15 [9752] [CRITICAL] WORKER TIMEOUT (pid:9787)
2014-04-07 13:15:15 [9752] [CRITICAL] WORKER TIMEOUT (pid:9787)
2014-04-07 13:15:16 [9809] [INFO] Booting worker with pid: 9809
connect
2014-04-07 13:15:21 [9752] [CRITICAL] WORKER TIMEOUT (pid:9809)
2014-04-07 13:15:21 [9752] [CRITICAL] WORKER TIMEOUT (pid:9809)
2014-04-07 13:15:22 [9830] [INFO] Booting worker with pid: 9830

Some notes:

  • it works perfectly if gevent is turned off (monkey patching and gunicorn worker class)
  • it works if db object is created per every incoming request
  • versions: gevent 1.0, gunicron 18.0, pymongo 2.6.2, flask 0.9, python 2.6.5

I doubt that this is a proper way to initialize and share a database pool. Still, I can't find anywhere if there is any other way to share an object between requests.

like image 294
Shcheklein Avatar asked Apr 07 '14 09:04

Shcheklein


People also ask

What is Gevent in Gunicorn?

gevent allows writing asynchronous, coroutine-based code that looks like standard synchronous Python. It uses greenlet to enable task switching without writing async/await or using asyncio . eventlet is another library that does the same thing.

Is PyMongo asynchronous?

pymongo is synchronous unlike its javascript counter part.


1 Answers

Ok, it was the same issue as:

https://jira.mongodb.org/browse/PYTHON-607

Workarounds that worked for me:

from gevent import monkey
monkey.patch_all()

unicode('foo').encode('idna')

...

or:

shcheklein@hostname:~$ export GEVENT_RESOLVER=ares
shcheklein@hostname:~$ gunicorn -w 1 -k gevent -t 5 --debug test:app
like image 93
Shcheklein Avatar answered Sep 19 '22 08:09

Shcheklein