Python Uwsgi
# Comprehensive Guide to Python uWSGI: Installation, Configuration, and Deployment
uWSGI is a highly versatile, high-performance application server container written in C. It is widely used in production environments to serve Python web applications by implementing the WSGI (Web Server Gateway Interface) specification.
This tutorial provides a comprehensive guide to installing, configuring, and deploying Python applications using uWSGI, covering raw WSGI applications as well as popular frameworks like Django and Flask.
---
## 1. Introduction to WSGI, uwsgi, and uWSGI
Before diving into the implementation, it is important to understand three easily confused terms:
* **WSGI**: A Python standard (PEP 3333) that defines a common interface between web servers and Python web applications.
* **uwsgi**: A fast, wire-level protocol used by the uWSGI server to communicate with a companion web server (such as Nginx).
* **uWSGI**: The actual application server software that implements both the WSGI specification and the uwsgi protocol.
---
## 2. Installation
To install uWSGI, you first need to install the required system development tools and Python headers.
### Prerequisites (Ubuntu/Debian)
Run the following command to install the necessary build dependencies:
```bash
sudo apt-get update
sudo apt-get install build-essential python3-dev
```
### Installation Methods
You can install uWSGI using one of the three methods below:
#### Method 1: Via pip (Recommended)
The easiest and most common way to install uWSGI is using Python's package manager:
```bash
pip install uwsgi
```
#### Method 2: Via One-Line Install Script
You can download and run the official installation script, which compiles and places the uWSGI binary into a custom directory (e.g., `/tmp/uwsgi`):
```bash
curl http://uwsgi.it/install | bash -s default /tmp/uwsgi
```
#### Method 3: From Source
If you need to compile uWSGI manually from the latest source code:
```bash
wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar zxvf uwsgi-latest.tar.gz
cd uwsgi-latest
make
```
After compilation completes, a `uwsgi` executable binary will be generated in the current directory.
---
## 3. Creating Your First WSGI Application
Let's start with a basic "Hello World" WSGI application. Create a file named `foobar.py` with the following code:
```python
def application(env, start_response):
# Set the HTTP response status and headers
start_response('200 OK', [('Content-Type', 'text/html')])
# Return the response body as bytes
return
```
> **Note:** The uWSGI Python loader searches for a callable named `application` by default.
### Running the Application
To start an HTTP server running your application on port `9090`, execute:
```bash
uwsgi --http :9090 --wsgi-file foobar.py
```
You can now open your browser and navigate to `http://localhost:9090` to see "Hello World".
---
## 4. Adding Concurrency and Monitoring
By default, uWSGI starts with a single process and a single thread. For production environments, you should scale this up.
### Configuring Processes and Threads
You can use the `--processes` (or `-p`) and `--threads` options to handle concurrent requests. The `--master` option is highly recommended to manage worker processes.
```bash
uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2
```
* `--master`: Enables the master process to manage worker lifecycles.
* `--processes 4`: Spawns 4 worker processes.
* `--threads 2`: Spawns 2 threads per worker process (totaling 8 concurrent threads).
### Monitoring with the Stats Server
uWSGI includes a real-time statistics subsystem that exports metrics in JSON format. You can enable it by appending the `--stats` option:
```bash
uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
```
To view these statistics in a user-friendly, command-line interface similar to the Linux `top` utility, install and run `uwsgitop`:
```bash
pip install uwsgitop
uwsgitop 127.0.0.1:9191
```
---
## 5. Integrating with a Web Server (Nginx)
For production deployments, it is best practice to place a reverse proxy server like Nginx in front of uWSGI. Nginx handles static files, SSL/TLS termination, and slow clients, while forwarding dynamic requests to uWSGI.
### Step 1: Configure Nginx
Add the following block to your Nginx configuration file (typically located in `/etc/nginx/sites-available/default`):
```nginx
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
}
```
This configuration tells Nginx to forward incoming web traffic on the root path to the uWSGI server listening on port `3031` using the high-performance `uwsgi` protocol.
### Step 2: Start uWSGI with a Socket
Now, start uWSGI using the `--socket` option instead of `--http`:
```bash
uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
```
> **Note on HTTP Sockets:** If your upstream proxy server communicates strictly via HTTP rather than the native `uwsgi` protocol, use `--http-socket` instead of `--socket`:
> ```bash
> uwsgi --http-socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
> ```
---
## 6. Deploying Web Frameworks
### Deploying Django
Assuming your Django project is located at `/home/foobar/myproject`, you can run it using the following command:
```bash
uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --wsgi-file myproject/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
```
* `--chdir`: Changes the current working directory to your Django project root before loading the application.
* `--wsgi-file`: Points to the auto-generated `wsgi.py` file inside your Django project configuration directory.
#### Using an INI Configuration File
Instead of typing long commands in the terminal, you can define your configuration in an `.ini` file (e.g., `uwsgi.ini`):
```ini
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
wsgi-file = myproject/wsgi.py
master = true
processes = 4
threads = 2
stats = 127.0.0.1:9191
vacuum = true
```
To start uWSGI with this configuration file, simply run:
```bash
uwsgi uwsgi.ini
```
---
### Deploying Flask
Flask requires you to explicitly point uWSGI to the application callable inside your script.
Create a Flask application file named `myflaskapp.py`:
```python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Hello from Flask!"
```
To run this Flask application, use the `--callable` option to tell uWSGI where the Flask instance (`app`) is defined:
```bash
uwsgi --socket 127.0.0.1:3031 --wsgi-file myflaskapp.py --callable app --processes 4 --threads 2 --stats 127.0.0.1:9191
```
---
## 7. Key Considerations for Production
* **Master Process (`master = true`)**: Always run with the master process enabled. It ensures that dead workers are automatically respawned and handles graceful reloads.
* **Vacuum (`vacuum = true`)**: Clean up environment files and sockets (like Unix `.sock` files) automatically when the server stops.
* **Unix Sockets vs. TCP Sockets**: For Nginx and uWSGI running on the same physical machine, use Unix sockets (e.g., `socket = /tmp/uwsgi.sock`) instead of TCP ports (`127.0.0.1:3031`) to reduce overhead and improve performance. Remember to manage file permissions on the socket file.
* **Buffer Size**: If your application receives large request headers (e.g., heavy cookies or headers), you may need to increase the buffer size using `buffer-size = 32768` in your configuration.
YouTip