Working with Gunicorn WSGI server

So, I’ve been working on some cool projects lately using Gunicorn to host Flask-based APIs. And let me tell you, Gunicorn is awesome!

Basically, Gunicorn uses a pre-forking technique where it spins up a Python interpreter and all the required libraries of the Python application. This means that when a request comes into the server, it can be processed faster because everything’s already loaded up. Back in the day, CGI would have to load the app when the request came in, which made things slower and had other issues.

Here is what ChatGPT has to say about Gunicorn:

“Gunicorn is a web server for Python applications that can handle multiple worker processes to handle requests. It is highly compatible with popular web frameworks such as Flask and Django and implements the WSGI specification, which defines how web servers and Python web applications can communicate with each other. Gunicorn can be installed using pip, and a Python web application can be deployed on the Gunicorn server by creating a wsgi.py file that imports the application and runs it using Gunicorn. The number of worker processes and other server configurations can be customized using command line flags.”

Setting up Gunicorn at first took some research, but the common deployment usually goes like this: Ngnix >>> Gunicorn >>> Flask/Django app. In this chain, Ngnix proxies the web request over to Gunicorn, which then serves the app. But why does Ngnix handle the web request if Gunicorn is a web server? Well, the reasoning behind this is to have Ngnix, a true web server, handle all the HTTP requests and security items such as SSL, and leave the WSGI stuff to Gunicorn.

Here’s an example app:

from flask import Flask
app = Flask(__name__)
@app.route(‘/’)
def hello_world():
return ‘Hello, World!’


Now to install Gunicorn you actually use PIP to install it

pip3 install gunicorn

It’s a simple Flask site, but it’s best to make a Python virtual environment for your apps – it’s nice to package them up and move them from server to server. Running Gunicorn looks like this:

. api/bin/activate
(api) bash-4.4$ gunicorn –config unicorn.conf.py -w 4 main:app


And what’s unicorn.conf.py, you ask? That’s the config file for Gunicorn! Here’s what it looks like:


#!/usr/bin/env python
# This is a config file for Gunicorn
import multiprocessing
bind = “127.0.0.1:8000”
workers = multiprocessing.cpu_count() * 2 + 1
worker_connections = 1000
timeout = 30
keepalive = 2
threads = 2
daemon = False
debug = False
spew = False
preload_app = False
reload = True
graceful_timeout = 30
limit_request_line = 4094
limit_request_fields = 100
limit_request_field_size = 8190
raw_env = []
pidfile = None
umask = 0
user = ‘api’
group = ‘api’
tmp_upload_dir = None
secure_scheme_headers = {
‘X-FORWARDED-PROTOCOL’: ‘ssl’,
‘X-FORWARDED-PROTO’: ‘https’,
‘X-FORWARDED-SSL’: ‘on’,
}
# Logging
accesslog = “/tmp/unicorn_access.log”
errorlog = “/tmp/unicorn_error.log”
loglevel = “info”
capture_output = False
enable_stdio_inheritance = False
proc_name = None

That’s all I have for now. Until next time!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.