Gunicorn multi-threading with MySQL

1.6k views Asked by At

I am trying to run a simple NGnix + Gunicorn + Django + MySQL (RDS on AWS) stack, but obviously anything happening to some MySQL query will slow down and lock down the service.

To prevent that, I started using eventlet (which also plays nice with Celery), but patching MySQLdb seems to result in performance loss (2-3x response time) and instability (may lock down all db connection for a few seconds during restart).

Celery + eventlet with the same logic seem to work just fine, so what am I missing?

try:
    import eventlet

    worker_class = 'egg:gunicorn#eventlet'
    worker_connections = 1000
    def do_post_fork(server, worker):
        eventlet.monkey_patch()
        eventlet.monkey_patch(MySQLdb=True)

    post_fork = do_post_fork
except ImportError as e:
    import logging
    logging.exception(e)
    pass

Thanks!

1

There are 1 answers

1
temoto On

Slow query should not slow down the whole service. Only one particular request should be. Other workers are able to serve other requests.

You may try using just lots of single thread gunicorn workers. They will eat a lot of memory, but it's the most robust solution.

I'm not an AWS expert, so the following is a wild guess.

Unfortunately, mysqldb is C extension, so there is not way to patch it "properly". Instead eventlet uses thread pool to make mysqldb greenthread friendly.

Pre Python3.3 threads waste lots of CPU resources for no good reason. So your performance issues may be due to bad compatibility of greenlet, Python threads and AWS virtualization. Again, I don't know exact reason, it's a guess.