There is some standart stack to run django in production. For python 2, it is nginx + gunicorn or uwsgi + monkey patching libs, such as gevent or eventlet. Generally, I prefer gunicorn + eventlet, but when you switch (or start) django project on latest python 3.5, eventlet can do some bad magic. And you can switch to a new built-in mechanism, called aiohttp. Based on gunicorn docs, you need simply switch worker to gaiohttp and that’s all.
Then, something bad happens.
Answer is very simple:
you write some memoryleaking code gaiohttp ignores max_requests option.
In other words, workers won’t be killed after max_requests count. After some search on internet, there is an article from asyncio contributor about copy-n-pasting worker from aiohttp repo to gunicorn.
Aiohttp docs says that you should use
aiohttp.worker.GunicornWebWorker, but when you switch setting there will be error.
 [ERROR] Exception in worker process Traceback (most recent call last): File "./gunicorn/arbiter.py", line 557, in spawn_worker worker.init_process() File "./aiohttp/worker.py", line 37, in init_process super().init_process() File "./gunicorn/workers/base.py", line 132, in init_process self.run() File "./aiohttp/worker.py", line 40, in run self.loop.run_until_complete(self.wsgi.startup()) AttributeError: 'WSGIHandler' object has no attribute 'startup'
So aiohttp.worker.GunicornWebWorker differs from standart wsgi app for django. Luckily, python community has two packages to overcome these difficulties: aiohttp-wsgi and aiodjango, add them to your requirements.txt. After this modify your wsgi.py according to docs:
import os from django.core.wsgi import get_wsgi_application from aiodjango import get_aio_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') # Build WSGI application # Any WSGI middleware would be added here application = get_wsgi_application() # Build aiohttp application app = get_aio_application(application)
That’s all folks.