How to Deploy Python WSGI Applications Using uWSGI Web Server with Nginx
Understanding uWSGI and Using Nginx
uWSGI is an ambitious project. Its toolset allows you to do so much more than simply hosting web applications. Since it does the job so well, and in such a performant way, over the years it has proven to be an indispensable tool for many system administrators and developers alike when it comes to deploying their applications.
Nginx, since version 0.8.40 supports the uwsgi protocol (uWSGI's own). This enables the WSGI applications running on uWSGI to communicate the best way possible with Nginx. What this means for you is the possibility of very simple-to-configure deployments which are highly flexible (and functional) and benefiting from many under-the-hood optimizations that comes along. Altogether, this makes uWSGI coupled with Nginx an excellent choice for many deployment scenarios.
uWSGI in Brief
"Despite its very confusing naming conventions, uWSGI itself is a vast project with many components, aiming to provide a full software stack for building hosting services. One of these components, the uWSGI server, runs Python WSGI applications. It is capable of using various protocols, including its own uwsgi wire protocol, which is quasi-identical to SCGI. In order to fulfil the understandable demand to use stand-alone HTTP servers in front of application servers, NGINX and Cherokee web servers are modularised to support uWSGI's [own] best performing uwsgi protocol to have direct control over its processes.”
Web Application Deployments with Nginx
Nginx is a very high performant web server / (reverse)-proxy. It has reached its popularity due to being light weight, relatively easy to work with and easy to extend (with add-ons / plug-ins). Thanks to its architecture, it is capable of handling a lot of requests (virtually unlimited), which - depending on your application or website load - could be really hard to tackle using some other, older alternatives.
Using Nginx as Reverse-Proxy with uWSGI
As your application grows, you will want to optimise it and when the time comes, distribute it across servers to be able to handle more connections simultaneously and have a generally more robust architecture. Having a reverse-proxy in front of your application server(s) helps you with this from the very beginning.
Nginx's extensibility (e.g. native caching along with failover and other mechanisms) is also a great feat that benefits web applications unlike (simpler) application servers.
Example of a Basic Server Architecture:
Note:When an application is set to listen for incoming connections on
Preparing Your Server Instance for Production
In this section, we are going to prepare our virtual server for production (i.e. for deploying our application).
We will begin with:
Updating the default operating system
To ensure that we have the latest available versions of default applications, we need to update our system.
For Debian Based Systems (i.e. Ubuntu, Debian), run the following:
For RHEL Based Systems (i.e. CentOS), run the following:
Setting up Python, pip and virtualenv
On Ubuntu and Debian, a recent version of Python interpreter which you can use comes by default. It leaves us with only a limited number of additional packages to install:
python-devis an operating-system level package which contains extended development tools for building Python modules.
Run the following command to install python-dev using aptitude:
pipis a package manager which will help us to install the application packages that we need.
Run the following commands to install pip:
It is best to contain a Python application within its ownenvironmenttogether with all of its dependencies. An environment can be best described (in simple terms) as an isolated location (a directory) where everything resides. For this purpose, a tool called virtualenv is used.
Run the following to install virtualenv using pip:
Creating a self-contained Virtual (Python) Environment
Having all the necessary tools ready at our disposal, we can create an environment deploy our application.
Remember: If you haven't got a virtualenv on your development (local) machine for your project, you should consider creating one and moving your application (and its dependencies) inside.
Let's begin with creating a folder which will contain both the virtual environment and your application module:
We can continue with entering this folder and creating a new virtual environment inside:
Let's create a new folder there to contain your Python application module as well:
And activate the interpreter inside the virtual environment to use it:
In the end, this is how your main application deployment directory should look like:
Downloading and installing uWSGI
It is always the recommended way to contain all application related elements, as much as possible, together inside the virtual environment. So we will download and install uWSGI as such.
If you are not working inside an environment, uWSGI will be installedglobally(i.e. available systemwide). This is not recommended. Always opt for usingvirtualenv.
To install uWSGI using pip, run the following:
Downloading and installing Nginx
Run the following command to use the default system package manager aptitude install Nginx:
To run Nginx, you can use the following:
To stop Nginx, you can use the following:
To restart Nginx, you can use the following:
Serving Python WSGI applications with uWSGI
In this section, we will see how a Python WSGI application works with uWSGI web server. Working with uWSGI to serve Python WSGI applications is not dissimilar to other application containers. What uWSGI needs, just like other servers, is for your application to provide it with an entry point (a callable). During launch, this callable, alongside configuration variables, are passed to uWSGI and it starts to do its job. When a request arrives, it processes it and passes it to your application's controller to handle.
WSGI in a nutshell is an interface between a web server and the application itself. It exists to ensure a standardized way between various servers and applications (frameworks) to work with each other, allowing interchangeability when necessary (e.g. switching from development to production environment), which is a must-have need nowadays.
WSGI Application Object (Callable): "wsgi.py”
As mentioned above, web servers running on WSGI need an application object (i.e. your application's).
With most frameworks and applications, this consists of a wsgi.py to contain and provide an application object (or callable) to be used by the server.
We will begin with creating an exemplary wsgi.py which then will be imported and used by uWSGI to run the application.
Let's begin with creating a wsgi.py file to contain a basic WSGI application.
Run the following command to create a wsgi.py using the text editor nano:
And let's continue with moving (copy/paste) the basic WSGI application code inside (which should be replaced with your own application's callable for production):
After placing the application code in, press CTRL+X and then confirm with Y to save this file inside the "my_app” folder alongside the virtual environment and the app module containing your actual application.
Note: This WSGI application is the most basic example to its kind. You will need to replace this code block to include your own application object from the application module.
Once we are done, this is how your main application deployment directory should look like:
Running the server
uWSGI has a lot of options and configurations with many possible ways of using them thanks to its flexibility. Without complicating things from the start, we will begin with working with it as simply as possible and continuing thereon with more advanced methods.
Simple usage example:
To simply run uWSGI to start serving the application from wsgi.py, run the following:
To run the server in the background, run the following:
[!] Important: When you run the server to work with Nginx using the configuration from the section Configuring Nginx, make sure to remove
Managing uWSGI server and processes with signals
Managing uWSGI consists of actions taken during runtime. There are various commands set for this task to manipulate the process:
Restarting the server with SIGHUP
This command gracefully restarts the server. What this means is, it waits for the current workers' job to be done, and then it terminates them before spawning them again, inheriting its settings.
Stopping the server with SIGINT
To stop the server and its processes, you need to use the
After setting up uWSGI to run our application, we now need to do the same with Nginx for it to talk with the uWSGI server(s). For this, we need to modify Nginx's configuration file:
Run the following command to open up
Afterwards, you can replace the file with the following example configuration to get Nginx work as a reverse-proxy, talking to your application.
Example configuration for web applications:
When you are done modifying the configuration, press CTRL+X and confirm with Y to save and exit. You will need to restart Nginx for changes to come into effect.
Run the following to restart Nginx:
When launching uWSGI to serve applications, there are several ways to supply it with necessary configurations such as the socket to run on, number of processes, master process settings etc. In this section, we will talk about three of them:
Option #1: Passing configurations as arguments:
Albeit easily getting confusing and hard to manage at times, the most basic way to run uWSGI is just like any other shell script - by supplying it the necessary configurations as arguments.
Option #2: Using
Another (and probably) a better way of providing uWSGI with configurations is through
Option #3: Using
Common configurations for uWSGI
As stated on its own documentation, the number of possible ways to configure uWSGI is almost infinite. In this section, we will try to go over the most commonly used or critical ones and explain the implementation, which when combined with the previous section, will enable you to have uWSGI running exactly the way you need it.
The syntax used in the examples below are targeted for
Sets uWSGI to be bound to a certain HTTP socket.
Sets uWSGI to be bound to specified socket using the default protocol.
Either term can be used to refer to the same thing: the amount of processes spawned to accept requests.
By default, uWSGI runs on its own uwsgi protocol. This property allows you to change it.
This option is used to enable or disable a master uWSGI process. These processes are used for managing workers which accept and deal with the incoming requests. The advantages are many, including gracefully restarting workers without touching the sockets which would allow you upgrades without downtime.
If you are worried about memory leaks and can not think of a more solid way of dealing with it, this option will allow you to restart your processes automatically after dealing with the set amount of requests specified.
Settings for running each process with the specified amount of threads in rethread mode. It is possible to combine this option withprocessesin order to obtain concurrency in varying degrees.
Used for disabling the logging feature.
Allows you to set the process name to something of your choice.
Set uWSGI server user
Set uWSGI server
Removes all generated pidfiles / sockets upon exit.
This setting daemonizes uWSGI and writes messages to supplied argument (log file).
Set uWSGI to write the process PID to a file specified by the option. This option is very handy for the management of uWSGI processes running (see the Managing uWSGI section for more information).
This setting is used to set the maximum amount of time a process is allowed to complete its task before it gets killed and recycled for memory / management purposes.
|Posted by: ASPHostServer Administrator - Sat, Jan 4, 2014 at 2:09 AM. This article has been viewed 2036 times.|
|Online URL: http://faq.asphosthelpdesk.com/article.php?id=266|