uWSGI is a fast (pure C code) and self-healing solution for python apps, but it's not easy to use.

15/02/2020 | Autor: Eduardo Enriquez

uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C. It's a deployment option on servers like nginx, lighttpd, and cherokee.

How does it work?

uWSGI operates on a client-server model. Your Web server (e.g., Nginx, Apache) communicates with a django-uwsgi “worker” process to serve dynamic content. In the configuration of uWSGI, you can decide how many workers (processes, threads) you want for your app. Try to follow all the configs that I share because default values are all wrong (you should check this europython talk to know more about it).

How can I run it?

uWSGI supports multiple ways to configure the process.

uwsgi --chdir=/path/to/your/project \
    --module=mysite.wsgi:application \
    --env DJANGO_SETTINGS_MODULE=mysite.settings \
    --master --pidfile=/tmp/project-master.pid \
    --socket= \                   # can also be a file
    --processes=5 \                              # number of worker processes
    --uid=1000 --gid=2000 \                      # if root, uwsgi can drop privileges
    --harakiri=20 \                              # respawn processes taking more than 20 seconds
    --max-requests=5000 \                        # respawn processes after serving 5000 requests
    --vacuum \                                   # clear environment on exit
    --home=/path/to/virtual/env \                # optional path to a virtualenv
    --daemonize=/var/log/uwsgi/yourproject.log   # background the process

Or you can run your application with a config file (.ini) like this:

uwsgi --ini uwsgi.ini

For Django:

# If you want to use it with nginx-proxy (jwilder) and VIRTUAL_PROTO
# for running inside of docker
socket =
#http-socket =
# if you dont want to run it with sudo
# for naming
# clear environment on exit
vacuum = true
# check sintax error on this file
# master uWSGI’s built-in prefork+threading multi-worker management mode
master = true
# allows threading module on python (not only for our code also for third-parties)
# accpets kill signal SIGTERM
# checks if the app is up
# there are reports on some C extensions that do not cooperate well with multiple interpreters
# logss are super noisy
logformat="%(method) %(uri) %(proto) %(status)" %(user) %(addr) %(uagent) from %(referer)

# Workers (these can be processes and threads but because of GIL is better to go for processes)
# How many? cpu cores * 2 (but it needs to be checked by running uwsgitop /tmp/uwsgi-stats.socket)
processes = 2
# restart workers after this many requests
# restart worker after this many seconds
# restart worker after this much of resident memory
# How many minutes uwgsi needs to wait before forcefully killing workers
# forcefully kill workers after 20 seconds. SIGKILL if the worker doesnt respond
# allow the workers to recieve signals such as signal.alarmm from the OS (not working for alpine)
# py-call-osafterfork=true
# Django-related settings
# the base directory (full path)
# Django's wsgi file
# the virtualenv (full path)
# home=/usr/local/bin/
# Track statistics for easier peformance tuning
#stats = /tmp/uwsgi-stats.socket
#touch-reload = /tmp/reload-uwsgi

Gunicorn is easy for starting a project. But if you have more time and you want to have the possibility of better setups go for uwsgi. Try to read carefully the docs!

How to debug it?

There is a great tool for debugging uWsgi: uwsgitop is a top-like command that uses the stats server. It is available on PyPI, so use easy_install or pip to install it. You can check the code: https://github.com/xrmx/uwsgitop

#To use uWSGI Stat Server simply use the stats option followed by a valid socket address,
# for example:

uwsgi --module myapp --socket :3030 --stats /tmp/stats.socket

# To start monitoring your application with uwsgitop call it with the socket address like so:

uwsgitop /tmp/stats.socket

# If you want the stats served over HTTP you will need to add the stats-http option in uWSGI:

uwsgi --module myapp --http :3030 --stats :3031 --stats-http

# You'll now need to call uwsgitop as: