Hello world!
Today, we are going to see the best way to serve a django or flask app using bjoern. As you might know, bjoern is a wsgi server. Currently it is considered as the fastest server. You can check this link https://www.appdynamics.com/blog/engineering/a-performance-analysis-of-python-wsgi-servers-part-2/
We assume you already install bjoern
in your environment. Git their github for instructions https://github.com/jonashaag/bjoern
The code
Here is the code to serve a django app
This code must be placed in the same folder with manage.py
The explanations
Now let's study it.
We import the required packages, first
import bjoernfrom pathlib import Path
import socket
import sys
import os
import traceback
from django.core.wsgi import get_wsgi_application
We dynamically get the project name, instantiate the django wsgi application and declare the server_address we will use.
proj_name = Path(os.path.abspath(__file__)).parent.name
os.environ.setdefault('DJANGO_SETTINGS_MODULE', f'{proj_name}.prod')
application = get_wsgi_application()
server_address = f'/tmp/{proj_name}.sock'
Now we must remove any existing unix socket so we don't get any error on creation
try:
os.unlink(server_address)
except OSError:
if os.path.exists(server_address):
os.remove(server_address)
We create the socket and change his access mode you any server can access it
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(server_address)
sock.listen()
print("Setting access mode to 777")
os.chmod(server_address, 0o777)
Finally, we tell bjoern to run via the websocket
try:
print(f"Serving {proj_name} via {server_address}")
bjoern.server_run(sock, application)
except Exception as e:
traceback.print_exc()
try:
sock.close()
except:
traceback.print_exc()
try:
os.remove(server_address)
except:
traceback.print_exc()
Some considerations
Why you should use unix sockets over regular tcp sockets? In a production environment taking care of which tcp port is assigned to each app or service is tricky. It is a lot easier to work with unix socket because they are defined using names. Using the file serve.py we just studied for every project you serve you will have a related unix socket.
It is also known that unix sockets are slightly faster than tcp sockets. For a big project this can have a good impact.
Flask
Serving flask is the same as serving django. you just have to import your flask app. For example if your flask app lives in main.py, you will import it like this
from main import app as application
Bonus: Nginx
To exploit this method, you must use a web server in reverse proxy. Here is a configuration example for nginx
upstream [proj_name]{
server unix:/tmp/[proj_name].sock;
}
server {
server_name [proj_domain];
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /[proj_path];
}
location /media/ {
root /[proj_path];
}
location / {
include proxy_params;
proxy_set_header X-Forwarded-SSL 'on';
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Referer $http_referer;
add_header Referer $http_referer;
proxy_pass http://[proj_name];
}
listen 80;
}
We reached the end of our article. I wish you like it. Stay tuned!