Full Blog TOC

Full Blog Table Of Content with Keywords Available HERE

Sunday, January 19, 2025

Gunicorn



 


In this post we review usage of the python framework Guicorn.

Gunicorn provides a concurrent processing of sockets request, while using a polling mode that enables the same worker to handle multiple requests.


A Simple Flask Application

Gunicorn can be used to wrap the flask application. For example, let's assume we have the following flask application code:


main.py

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
return "Hello World"

if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)

We deploy the dependencies:

pip install flask

and run the application:

python main.py


Let's stress test the flask application without gunicorn, first install the apache stress tool:

sudo apt install apache2-utils

and next run the stress with 10K requests and concurrency of 10 threads:

ab -n 10000 -c 10 http://localhost:8080/

The results are:



Wrap the Flask with Gunicorn

To wrap the flask application with gunicorn, we deploy:

pip install gunicorn


and run gunicorn:

gunicorn --workers=2 'main:app'


Notice that guicorn starts by default on the port 8000, so let's run the stress test:

ab -n 10000 -c 10 http://localhost:8000/

The results are:



And we've got ~10 times better results, which is pretty amazing.


Final Note

Using guicorn seems to make python run like a real multithreaded application, however we must be aware to the fact that gunicorn spawns workers processes, hence swe cannot share memory between the workers. 

Using guicorn is a nice solution if we do not have the resources to rewrite the application in GO, but notice that running gunicorn in kubernetes is a bad practice as the guideline is: 

one container == one process

and gunicorn does not follow it. Still, it is reasonable solution for non-critical services.





No comments:

Post a Comment