uwsgi has a concept of hard timeouts, which they call “harakiri”. This is a useful tool to ensure that your web workers don’t hang too long on a single request. The setting configures how many seconds a worker can spend on a request, and if the worker takes longer, it will be forcefully killed from outside the Python process. This means that if your Python code is hanging on e.g. a slow database query or network request, it will be killed and a new worker will be spawned in its place. The client that started the request will get an error response from uwsgi.
Configuring harakiri
The simplest way to configure harakiri is to just enable a global setting in your uwsgi.ini
config.
harakiri = 5
However, in an existing application you might not be able to enforce such a strict timeout right away. A better strategy might be to have a strict default, but exempt certain endpoints that are nontrivial to speed up.
uwsgi provides a Python API, which means you can configure a harakiri timeout inside your request handling, typically in a middleware. The following example is a Django middleware that sets different harakiri timeouts based on the request path and method.
HARAKIRI_REGEX = re.compile(rf'^(/slow_paths/.*|/other_slow/)$')
class HarakiriMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
try:
import uwsgi
self.uwsgi = uwsgi
except ImportError:
self.uwsgi = None
def __call__(self, request: HttpRequest):
if self.uwsgi is None:
return self.get_response(request)
if HARAKIRI_REGEX.match(request.path):
self.uwsgi.set_user_harakiri(30) # Give 30s harakiri to slow endpoints
elif request.method == 'GET':
self.uwsgi.set_user_harakiri(2) # Give 2s to GET requests
else:
self.uwsgi.set_user_harakiri(5) # Give 5s to all other requests
try:
return self.get_response(request)
except Exception:
raise
finally:
self.uwsgi.set_user_harakiri(0) # Unset harakiri, so that next request does not get a harakiri value until it sets it itself.
And then you add this middleware to your settings.MIDDLEWARE
list, preferably in the beginning of the list so that any slowness in your middlewares would also be included in the harakiri timeout.