Hello,
I am sure I must be missing something but I don't know how I should go about it. I have a ASW medium instances that are struggling with 20-30 RPS, which I consider terrible performance.
Let me tell you a bit about how I run things:
- the Django application exposes a rest API interface using Django REST Framework
- the Django is running on uwsgi. Each UWSGI process is configured not to use threads, because of GIL in Python.
- I use nginx in front of uwsgi
- each instance runs 50 uwsgi processes. Because UWSGI threads are not enabled, and because of the synchronous nature of Django (as opposed to Twisted on node.js) this means that each uwsgi process can only run 1 request at a time.
- some requests take longer to execute (they might access 3rd party APIs or do multiple DB calls)
The problem is that while all uwsgi processes are waiting for other services to respond they can not accept other requests. So requests keep getting buffered waiting to execute. I can not increase the number of uwsgi processes, because I already max out on CPU (all this context switching between the processes must be expensive because I am basically using processes for what would be threads in Java). I did try both more and less than 50 uwsgis/instance and 50 seemed to allows the maximum number of RPS (but still very very few).
Question:
In Java for example each request would be handled by a thread. And you can have 10000 threads running at a time easily. This means that even though each request takes a long time (waiting for other services to respond - so idle time for the thread), it can still execute thousands of RPS so it has a very good throughput.
However because with uwsgi, I am using a uwsgi as a thread, the uwsgi process is much more heavy than a Java thread, so I can run only 50. This means a much lower throughput.
What am I missing? I would really appreciate your advice. I could not find anything and I have been looking for days for a solution. It just feels like the throughput performance is so so terrible for Django, and I will need 20 instances for what Java could handle on 1.
Thank you,
Ryan
PS: This is the uwsgi configuration. I run multiple wsgis using emperor.
[uwsgi]
project = frontend-api
base = /home/django
chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = apps.frontend.uwsgi:application
master = true
processes = 50
socket = /tmp/%(project).sock
chmod-socket = 666
vacuum = true
stats = /tmp/frontend-api-stats.sock
memory-report = true
pythonpath = /home/django/frontend-api/src