python USES Nginx and uWSGI to run Python applications

  • 2020-06-23 01:06:55
  • OfStack

uWSGI is an Web application server with application server, agent, process management and application monitoring functions. It supports the WSGI protocol, as well as its own uWSGI protocol, which is said to have very high performance and low memory footprint, about half of mod_wsgi, which I haven't measured. It also supports multi-application management and application performance monitoring. Although uWSGI itself can be used directly as an Web server, it is generally recommended that it be used as an application server in conjunction with Nginx1 to better leverage the power of Nginx on the Web end. In this article, we introduce how to build uWSGI+Ngnix environment to run Python application.

Install uWSGI


pip install uwsgi

Let's write Hello World's WSGI app and save it in the "server.py" file:


def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(output)))]
  start_response(status, response_headers)
 
  return [output]

Let's run it in uWSGI and execute the command:


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

Then open your browser and go to "http://localhost:9090" and you will see "Hello World!" With the words.

In the above command, the "-ES39en" parameter specifies the HTTP listening address and port, and the "-wsgi-ES42en" parameter specifies the WSGI application entry. uWSGI automatically searches for and invokes the application object named "application".

Further, uWSGI can support multi-process and multi-threaded startup of applications, as well as monitor the health of applications. We changed the start command to:


$ uwsgi --http :9090 --wsgi-file server.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

After executing it, uWSGI will start four application processes, with two threads per process, and one master main process (monitor the status of other processes and restart if any processes die). At the same time, you can access the "127.0.0.1:9191" to get the application running information in JSON format. uWSGI also provides the tool command "uwsgitop" to monitor the application running status like top1. You can use pip to install it.

The above command has too many parameters, we can write the parameters in the configuration file, when starting uWSGI, we can specify the configuration file. The configuration file can be in the key-value pair format or XML, YAML format, which we use here. Let's create a profile "myapp.ini" :


[uwsgi]
http=:9090
wsgi-file=server.py
master=true
processes=4
threads=2
stats=127.0.0.1:9191

You can then simplify the boot command to:


$ uwsgi myapp.ini

Configuration Nginx

The installation of Nginx can be referred to in this article. The environment used for the text is Ubuntu Linux. For other systems such as Mac, it is basically not too bad

First, we change the HTTP port listening of uWSGI to socket port listening. Remove the "http" item in the configuration file and change it to "socket" item:


[uwsgi]
socket=127.0.0.1:3031
wsgi-file=server.py
master=true
processes=4
threads=2
stats=127.0.0.1:9191

Then, open the configuration file of Nginx, the default on Ubuntu is "/etc/nginx/ sites-ES96en /default", and configure the root path part of it as:


location / {
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:3031;
}

This configuration indicates that Nginx forwards all requests received to port 127.0.0.1:3031, the uWSGI server. Now let's restart Nginx and start the uWSGI server:


$ sudo service nginx restart
$ uwsgi myapp.ini

Visit "http://localhost" and we will see "Hello World again!" .

Run the Flask application

It's as simple as changing server. py to Flask app, but you need to install Flask first:


from flask import Flask
application = Flask(__name__)
 
@application.route('/')
def index():
  return '<h1>Hello World</h1>'

Many people use the name Flask as "app", but WSGI is "application". uWSGI provides the ability to specify application objects by adding the "callable" entry to the configuration file:


[uwsgi]
...
callable=app

Now, our Flask application can use "app" as the object name


def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(output)))]
  start_response(status, response_headers)
 
  return [output]
0

Use the Python virtual environment

We always recommend using a virtual environment to avoid conflicts between applications. uWSGI can easily do this by adding "virtualenv" to the configuration file:


def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(output)))]
  start_response(status, response_headers)
 
  return [output]
1

Deploy multiple applications

In one Nginx, multiple applications can be run at the same time, not necessarily the Python application. We expect to route different applications through different paths, so we cannot directly modify the configuration of the root directory as in the previous example. Suppose we hope that through "http: / / localhost myapp" to access our application, must first in Nginx configuration file, add the following content:


def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(output)))]
  start_response(status, response_headers)
 
  return [output]
2

Here we define an uWSGI parameter "SCRIPT_NAME", which is the path of the application "/myapp". Next, in the uWSGI startup configuration, remove the "wsgi-ES163en" TAB and add:


[uwsgi]
...
mount=/myapp=server.py
manage-script-name=true

The "mount" parameter means to route the "/myapp" address to "ES169en.py", and the "ES171en-ES172en-ES173en" parameter means to enable the "SCRIPT_NAME" parameter configured in Nginx before. Restart Nginx and uWSGI again, you can through the "http: / / localhost myapp" to access the application.

Add the content

In all of the above examples, we connected Nginx and uWSGI via the "127.0.0.1:3031" Socket port, but we could have used the socket file to avoid writing dead ports. In the startup configuration of uWSGI, we will modify the "socket" item:


def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(output)))]
  start_response(status, response_headers)
 
  return [output]
4

When the uWSGI server is started, it automatically creates a "/tmp/ uwsgi.sock" file. Then let's modify the Nginx configuration file to change the "uwsgi_pass" configuration item to a file:


def application(environ, start_response):
  status = '200 OK'
  output = 'Hello World!'
 
  response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(output)))]
  start_response(status, response_headers)
 
  return [output]
5

Restart the Nginx server. It took me a long time to find out that Nginx users (default ES207en-ES208en :adm) must have access to the file. Because the user running uWSGI is not the same as the user running Nginx, and "/tmp/ uwsgi.sock" was created by the user of uWSGI, Nginx does not have sufficient permissions. If your friends have the same problem, then chmod is the only option.

In addition, still should carry 1. "egg" pack unzip the temporary directory, we mentioned that at the end of the introduction mod_wsgi 1 sample in uWSGI applications, on Linux in user home directory by default, such as "/ home bjhee /. python - eggs". You can change this by setting the system environment variable "PYTHON_EGG_CACHE".


Related articles: