What happens when you click on a link to a web application built using Python Django web framework or just any other regular website? How can anybody from any part of the world access your web application anywhere?
Web applications use cloud resources (computers with storage, memory, and CPU) that distribute the files and folders to multiple users worldwide.
Cloud computers have web servers that utilize the Proxy protocol to process requests from different users.
Upon processing the requests, the web server requests the application server (Django or technology used to develop your website) to manipulate data in your files or database and provide feedback (HTML page, text, e.t.c).
The processed information passes through the web server again while being routed to the client application that made the request.
Web servers utilize HTTP, SSL, WebSocket, and TCP to communicate with the client applications.
How websites work
Websites or web applications work the same way you use your personal computers to save, edit, and delete data. Only in a web application can the files be accessible from anywhere. I mean, literally anywhere.
Well, not in space, not yet. But we’re getting there. Right, Elon?
But from any part of the globe, provided you have internet access that allows you to use the protocols used in communication between the server and client application (Web browser such as Chrome).
After opening your favorite web browser and typing the URL of a website or clicking on a link, the browser sends a request through the TCP protocol to the server (virtual machine) that hosts your web application files, folders, or a database.
All HTTP requests and responses between a server and a client application (web browser) use TCP, ensuring end-to-end communication and data sharing. The server then responds with an HTML page and the data requested.
But, a client application (web browser) communicates indirectly with a server using the web server (NGINX or Apache) residing on the server machine.
The web server handles requests from the client before the web application receives and processes the requests. The web server serves many purposes that include:
- Process and deliver webpages to users
- Manage incoming web traffic and distribute requests to upstream servers such as database server
- Serving static and media files to the client applications
- And most importantly, load balancing
Load balancing works this way.
Multiple users worldwide, probably thousands, will access your web application simultaneously.
What happens if the web server accepts the requests one at a time?
The web server would serve users one at a time leading to a very long queue of requests waiting to be processed. Bad user experience because users will have to wait for a page to load. Other times, the browser yells at them, TIMEOUT!
Will that user come back to your website? Hell Nah!
Here’s the bright side
The good thing about a web server is that it handles the requests simultaneously and synchronously.
A server with enough memory and CPU resources can process multiple requests in nanoseconds.
Good user experience, right?
Without synchronization, the server (computer) would just HAAAAANG! because too many requests being processed randomly would overwhelm the server.
A web server acts as a load balancer to route all the requests across all the servers (application servers, database servers) and microservices that can process them while maximizing performance speed and efficiency.
After the web server receives requests, it is not its work to process business logic (manipulate data in the database or files, for example).
No. It leaves all the business logic processing to an application server such as Django.
However, before the requests reach the application server, Django, they pass through a fast common gateway interface (FastCGI), Gunicorn. Take it more like a mediator or translator.
Another reason you would need a gateway interface is that there is intercommunication between different web technologies, where a C application (NGINX) communicates with a Python application (Django).
The application server must process data in the appropriate format to produce meaningful feedback.
That’s when the gateway interface comes in!
Gunicorn is a Python-based gateway interface HTTP server that allows Python applications (Django, Flask) to communicate with the web server software such as NGINX.
What are the functions of Gunicorn in a Django application?
Gunicorn acts as the NGINX web server and the Django application interface.
Without Gunicorn, the Python application (Django) wouldn’t understand the incoming requests from NGINX.
Therefore, the application server would not process input correctly, leading to incorrect business logic.
What other things does Gunicorn do?
As I stated earlier, your web application will receive a massive number of requests at any one time. With the NGINX server sending requests simultaneously, Gunicorn must be up for the task.
What does Gunicorn do after receiving these requests?
Well, it must improvise!
Instead of sending the requests to only one instance of your application, Gunicorn replicates multiple instances of your Django application and distributes the incoming requests to these instances.
Gunicorn takes care of all the running instances of your web application by distributing the incoming requests to various workers of your web application.
Each instance provides feedback, which Gunicorn sends to the web server.
After receiving the feedback data, the web server (Gunicorn) sends it back to the client application that had requested it. The client application responds with an OK status, informing the web server that all the information has been received.
Why do we need Gunicorn for Django?
- Serve your Django application on more than one thread
- Gunicorn can handle up to 5 worker processes that can process up to 40 concurrent requests
Can I use Gunicorn alone without the NGINX web server?
Well, you may be asking. If Gunicorn can receive requests and manage web workers, why would we need NGINX? Gunicorn can handle the request by replicating application instances depending on the number of requests made.
This approach may never work in a web application setup that needs to handle many users.
First, you will overwhelm the server resources (storage, memory, and CPU).
Secondly, and most importantly, your web application is easily susceptible to denial of service attacks.
Yeah, you read the word, D-O-S ATTACK!
A Denial of Service attack occurs when the server is overwhelmed by too many requests and direct connections with the client applications. It gets BLOATED! The web server cannot accept additional connections.
An overwhelmed server is just like a personal computer or mobile phone faced with a deadlock situation.
That moment when you have to wait for your computer to respond after opening too many tabs on Chrome. I know you, reader. Don’t you just pull the power cord or battery out in that situation? Please do not deny it!
The same happens to the server hosting your website’s files. If too many users make requests to Gunicorn, it can’t handle too much traffic and probably, pull the power cord out!
Once Gunicorn establishes a connection with a client application, it must maintain the connection before sending feedback.
However, once Gunicorn sends the feedback in the form of packets (remember, data is transmitted over the internet in small chunks called packets) to the client application, the client application must respond with OK status.
What happens if the client application is not responding?
The connection with that particular client application is maintained. Gunicorn will store the response data until the client application becomes responsive again.
Therefore, other client applications cannot make requests to your web application until the connections are released. The new client applications can no longer use the buffer as it is full.
If they cannot make a connection, that means your website is not available. It is up and running, but the users cannot access it. A D-O-S!
Therefore, you will need a web server like NGINX to solve these challenges.
Why we need NGINX for Django
- To handle a high volume of connections and requests
- Manage incoming traffic through reverse proxy and load balancing
- NGINX serves static content faster
- NGINX is efficient and lightweight. You do not have to worry about storage and memory requirements.
- Supports high traffic load while using minimum memory usage
- NGINX caches static content. Therefore, web resources such as assets files are not fetched each time a client application makes a request.
- Better caching enhances your website speed—faster website access speed enhances user experience.
NGINX can support parallelism (parallel execution of sub-tasks), maintain connections to thousands of users simultaneously, buffer slow or non-responsive client applications, and transmit large amounts of data simultaneously.
As NGINX can transmit large amounts of data simultaneously, it makes a suitable choice to serve your web application asset files.
Whenever a client application accesses your server, the web server supplies these asset files so that your web application looks formatted, nice looking, and animated.
Generally, when deploying a website, we have to set up the database server, application server, and web server. You can take different approaches to distribute these resources: on one machine or across different machines.
Different architectures you can use to host Django web applications
- 1 TIER ARCHITECTURE
- 2 TIER ARCHITECTURE
- 3 TIER ARCHITECTURE
1 TIER ARCHITECTURE
When you have low to medium traffic coming to your website, you can host your website on a single server that will respond to client requests, process the data, and handle the database queries within the same machine.
The web server (NGINX), Application server (Django), and database server reside within the same machine.
The 1 tier architecture is typical within a Shared hosting plan.
You purchase a shared hosting plan (affiliate link where you can purchase a hosting package at very cheap prices) with a web server and database provided.
You will have to set up the application using tools like cPanel to host your website. Check this article to know how to deploy Django using cPanel (Shared hosting).
Alternatively, you can also use a tiny virtual private server (VPS) to host your Django web application.
Check this article with all the details on setting up the Django project on a Linux server (VPS).
2 TIER ARCHITECTURE
After you start receiving a pretty large amount of traffic to your web application, you should consider moving your database server to a different server (machine) within the same hosting company or another.
A VPS hosting plan will definitely work well or use an already set up database server such as the AWS fully managed RDS databases.
In a 2 tier architecture, the application and web servers reside on one server while a database server resides on a different machine.
Using the 2 tier architecture for your Django project allows your website to handle enormous traffic while keeping a maximum uptime. The database server will be responsible for only one thing, handle the database queries while reducing the load on the application and web servers.
Users will be able to access your website without experiencing any issues such as lagging.
3 TIER ARCHITECTURE
Finally, we have the 3-tier architecture, the best setup you can implement to handle a tremendous amount of traffic. I am talking millions of requests coming to your web application.
This setup separates the web server, application server, and database server into three different servers each.
In a 2 tier architecture, too much processing from the web requests and business logic from the application server overloads the server.
A solution is to separate these servers and have each server on its machine. You can use a VPS or customized server for web, application, and database servers.
In AWS, you would set up a fully managed relational database (RDS) for the database server, EC2 for the application server, and EC2 for the web server.
You would install MySQL, PostgreSQL, and other relational database management systems on the RDS database server. On one EC2, you would install Django to handle all the business logic and NGINX to handle web requests.
The good thing about such a setup is that you can always fix bugs and optimize the servers independently.
Finally, you have one server that handles web requests (webserver) on a single machine, another server processing all the business logic (application server), and another server handling database queries (database server).
NGINX web server, Gunicorn(gateway interface), and Django (application server) work together.
After a browser makes a request using the URL of your website, NGINX will pass the request to Gunicorn, which then passes it to Django.
Django generates an HTML page and sends it back to Gunicorn, which sends the page to NGINX. NGINX will then send the HTML page with additional assets file to the browser, rendering all the user’s data.
Just like the way you are seeing this page.
You should have noticed that the assets files do not have to be processed by Gunicorn. NGINX directly serves them to the client application.
No conclusion today! I kinda told you too much.