Rigid translation of python uWSGI official documents

Keywords: socket Django Web Server Python

Articles Catalogue

1. What is uWSGI?

Recommend this blog post The difference and relationship between uwsgi, wsgi and nginx
A website = web framework (such as django, flask) + web server (such as uWSGI)

A distributed website = nginx (also a web server, load balancing, reverse proxy) + web framework (django, flask) + web server (such as uWSGI)

It should be noted that,

  • WSGI is a communication protocol.
  • uwsgi is a protocol. uwsgi is a line protocol rather than a communication protocol, which is often used for data communication between uwsgi servers and other network servers. uwsgi protocol is a protocol owned by uwsgi server.
  • uWSGI is a web server. uWSGI is a Web server that implements two protocols: uWSGI and WSGI.

2. uWSGI configuration

Because the configuration system is unified, each command-line option maps to the entries in the configuration file at 1:1.

# On the command line
uwsgi --http-socket :9090 --psgi myapp.pl

Mapping to the configuration file is

[uwsgi]
http-socket = :9090
psgi = myapp.pl

uWSGI supports loading configuration files in a variety of ways other than simple disk files

uwsgi --ini http://uwsgi.it/configs/myapp.ini # HTTP
uwsgi --xml - # standard input
uwsgi --yaml fd://0 # file descriptor
uwsgi --json 'exec://nc 192.168.11.2:33000' # arbitrary executable

That is to say, uWSGI can be configured in four file formats: ini,.xml,.yaml,.json.

2.1 Start an HTTP server

# foobar.py

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]

The default function application that the uWSGI Python loader will search for.
Next, we start uWSGI to run an HTTP server and deploy the program on HTTP port 9090:

uwsgi --http :9090 --wsgi-file foobar.py

2.2 Concurrent and monitoring

By default, uWSGI starts with a single process and thread. Adding more processes and threads through processes and threads, respectively, and both options can be used at the same time.

# This will result in four processes (two threads per process), one main process (which will regenerate the process after they die) and an HTTP server.
uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2

If you want to perform monitoring tasks, you can use the stats subsystem. The data format of monitoring is JSON:

# Send some requests to your application, then telnet to port 9191.
uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

We can install uwsgitop (like the Linux top command) to view monitoring data

2.3 Start uWSGI web server

Even though the uWSGI HTTP router has reliability and high performance, we still want to put the application in a fully functional Web server.

UWSGI supports HTTP, FastCGI, SCGI and their specific protocols called "uwsgi". The best-performing protocol is obviously uwsgi, which has been supported by nginx and heroke (all Apache modules are available).

The simple nginx configuration is as follows:

# Pass each request to a server with a bound port of 3031, the uwsgi protocol
location / {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:3031;
}

The following is not an HTTP server (the protocol used is not HTTP but uwsgi).

# A uWSGI server was generated (using the uwsgi protocol)
uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

# If your proxy/network server/router uses HTTP protocol, uWSGI must also use HTTP protocol.
# http itself produces a proxy
uwsgi --http-socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

Deployment of uWSGI in 2.4 django

django is a popular python web framework.
Suppose the project directory for django is / home/foobar/myproject.

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 is used to specify project paths.

It's impractical, silly and error-prone to deal with command lines that are so long up there. But don't be afraid! uWSGI supports various configuration styles. In this Quick Start, we will use the. ini file.

Assume that the name of the configuration file is yourfile.ini

[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
wsgi-file = myproject/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:9191

Then run it as follows:

uwsgi yourfile.ini

If your django version is less than 1.4, then running uWSIG on the command line requires more options.

uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --pythonpath .. --env DJANGO_SETTINGS_MODULE=myproject.settings --module "django.core.handlers.wsgi:WSGIHandler()" --processes 4 --threads 2 --stats 127.0.0.1:9191

Or the file configuration is as follows:

[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
pythonpath = ..
env = DJANGO_SETTINGS_MODULE=myproject.settings
module = django.core.handlers.wsgi:WSGIHandler()
processes = 4
threads = 2
stats = 127.0.0.1:9191

2.5 Deployment of uWSGI in flask

flask is a popular python web microframework.

Suppose this is my flask application.

# myflaskapp.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "<span style='color:red'>I am app 1</span>"

The configuration used on the command line is as follows:

uwsgi --socket 127.0.0.1:3031 --wsgi-file myflaskapp.py --callable app --processes 4 --threads 2 --stats 127.0.0.1:9191

The.ini configuration in flask is as follows:

[uwsgi]
 
socket = 127.0.0.1:5000     #  The address and port used to start the program, usually running the flask project locally.
                            #  Flask address and port 127.0.0.1:5000,
                            #  But on the server, the ports are set through uwsgi, and the projects are started through uwsgi.
                            #  That is to say, uwsgi was launched, and the project was launched.
chdir = /home/flaskproject/          #  Project catalogue
 
wsgi-file = manage.py      # The startup file for flask programs is usually run locally  
                           # Python management. py runserver to start the project
 
callable = app      	   #  application variable name enabled in program
 
processes = 4     	   #  Number of processors, number of processes
 
threads = 2     	   #  Number of threads
 
stats = 127.0.0.1:9191     #  Service address for obtaining uwsgi statistics
 
pidfile = uwsgi.pid        #  Save pid information for use when stopping service and restarting
 
daemonize = ./log/uwsgi.log  #  Record uwsgi running logs in the background runtime
 
lazy-apps = true             #  uwsgi cannot start the service when it needs to connect to cassandra. You can use this option to set up
 
master-fifo = /opt/mt-search/web-service/mfifo   # Use chain-reloading to restart work by work without interruption. The command is echo C > mfifo
 
touch-chain-reload = true
  

2.6 Deployment of uWSGI in web2py

The configuration file for uWSGI is as follows:

[uwsgi]
http = :9090
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8

In web2py, we used the HTTP server again, which binds a short couple of 9090.
In the case of https protocol, the configuration needs to be modified.

First, we generate our keys and certificates through openssl. (I don't know what the following code means, except that it generates three files: foobar.csr, foobar.key and foobar.crt)

openssl genrsa -out foobar.key 2048
openssl req -new -key foobar.key -out foobar.csr
openssl x509 -req -days 365 -in foobar.csr -signkey foobar.key -out foobar.crt

The configuration file is modified as follows.

[uwsgi]
https = :9090,foobar.crt,foobar.key
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8

Then we restart uWSGI and use https://protocol in the browser to access it.

3. Notes

If uWSGI is started without threads, Python GIL (python global interpreter lock) will not be enabled, so the threads generated by the application will never run. You may not like this choice, but remember that uWSGI is a language-independent server, so most of its choices are to keep it "unknown".

To maintain Python thread support without starting multiple threads of the application, simply add the enable-threads option (or ini-style enable-threads = true).

3.1 Virtual Environment

If you use a virtual environment in your project, you just need to add virtualenv = to it. (I don't know if that's true in the. ini configuration file.)

3.2 Security and Availability

For security reasons, avoid running uWSGI instances with root privileges. Use uid and gid options and delete permissions?

[uwsgi]
https = :9090,foobar.crt,foobar.key
uid = foo
gid = bar
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8

If you need to bind to a privileged port (such as HTTPS 443), use a shared socket. They are created before deleting permissions and can be referenced using the = N syntax, where N is the socket number (starting from 0):

[uwsgi]
shared-socket = :443
https = =0,foobar.crt,foobar.key
uid = foo
gid = bar
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8

A common problem with Web application deployment is "request jamming". All your threads / processes are blocked (blocked on request) and your application cannot accept more requests. To avoid this problem, you can set up a harakiri timer. It is a monitor (managed by the main process) that will destroy processes that exceed a specified number of seconds (carefully select the harakiri value). For example, you might want to destroy a process that blocks more than 30 seconds:

[uwsgi]
shared-socket = :443
https = =0,foobar.crt,foobar.key
uid = foo
gid = bar
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8
harakiri = 30

4. References

[1] Flask+uwsgi+nginx project deployment
[2] uWSGI Official Documents

Posted by jalbey on Tue, 13 Aug 2019 06:12:02 -0700