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