146 lines
4.7 KiB
ReStructuredText
146 lines
4.7 KiB
ReStructuredText
uWSGI
|
|
=====
|
|
|
|
`uWSGI`_ is a fast, compiled server suite with extensive configuration
|
|
and capabilities beyond a basic server.
|
|
|
|
* It can be very performant due to being a compiled program.
|
|
* It is complex to configure beyond the basic application, and has so
|
|
many options that it can be difficult for beginners to understand.
|
|
* It does not support Windows (but does run on WSL).
|
|
* It requires a compiler to install in some cases.
|
|
|
|
This page outlines the basics of running uWSGI. Be sure to read its
|
|
documentation to understand what features are available.
|
|
|
|
.. _uWSGI: https://uwsgi-docs.readthedocs.io/en/latest/
|
|
|
|
|
|
Installing
|
|
----------
|
|
|
|
uWSGI has multiple ways to install it. The most straightforward is to
|
|
install the ``pyuwsgi`` package, which provides precompiled wheels for
|
|
common platforms. However, it does not provide SSL support, which can be
|
|
provided with a reverse proxy instead.
|
|
|
|
Create a virtualenv, install your application, then install ``pyuwsgi``.
|
|
|
|
.. code-block:: text
|
|
|
|
$ cd hello-app
|
|
$ python -m venv venv
|
|
$ . venv/bin/activate
|
|
$ pip install . # install your application
|
|
$ pip install pyuwsgi
|
|
|
|
If you have a compiler available, you can install the ``uwsgi`` package
|
|
instead. Or install the ``pyuwsgi`` package from sdist instead of wheel.
|
|
Either method will include SSL support.
|
|
|
|
.. code-block:: text
|
|
|
|
$ pip install uwsgi
|
|
|
|
# or
|
|
$ pip install --no-binary pyuwsgi pyuwsgi
|
|
|
|
|
|
Running
|
|
-------
|
|
|
|
The most basic way to run uWSGI is to tell it to start an HTTP server
|
|
and import your application.
|
|
|
|
.. code-block:: text
|
|
|
|
$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app
|
|
|
|
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
|
|
*** Operational MODE: preforking ***
|
|
mounting hello:app on /
|
|
spawned uWSGI master process (pid: x)
|
|
spawned uWSGI worker 1 (pid: x, cores: 1)
|
|
spawned uWSGI worker 2 (pid: x, cores: 1)
|
|
spawned uWSGI worker 3 (pid: x, cores: 1)
|
|
spawned uWSGI worker 4 (pid: x, cores: 1)
|
|
spawned uWSGI http 1 (pid: x)
|
|
|
|
If you're using the app factory pattern, you'll need to create a small
|
|
Python file to create the app, then point uWSGI at that.
|
|
|
|
.. code-block:: python
|
|
:caption: ``wsgi.py``
|
|
|
|
from hello import create_app
|
|
|
|
app = create_app()
|
|
|
|
.. code-block:: text
|
|
|
|
$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app
|
|
|
|
The ``--http`` option starts an HTTP server at 127.0.0.1 port 8000. The
|
|
``--master`` option specifies the standard worker manager. The ``-p``
|
|
option starts 4 worker processes; a starting value could be ``CPU * 2``.
|
|
The ``-w`` option tells uWSGI how to import your application
|
|
|
|
|
|
Binding Externally
|
|
------------------
|
|
|
|
uWSGI should not be run as root with the configuration shown in this doc
|
|
because it would cause your application code to run as root, which is
|
|
not secure. However, this means it will not be possible to bind to port
|
|
80 or 443. Instead, a reverse proxy such as :doc:`nginx` or
|
|
:doc:`apache-httpd` should be used in front of uWSGI. It is possible to
|
|
run uWSGI as root securely, but that is beyond the scope of this doc.
|
|
|
|
uWSGI has optimized integration with `Nginx uWSGI`_ and
|
|
`Apache mod_proxy_uwsgi`_, and possibly other servers, instead of using
|
|
a standard HTTP proxy. That configuration is beyond the scope of this
|
|
doc, see the links for more information.
|
|
|
|
.. _Nginx uWSGI: https://uwsgi-docs.readthedocs.io/en/latest/Nginx.html
|
|
.. _Apache mod_proxy_uwsgi: https://uwsgi-docs.readthedocs.io/en/latest/Apache.html#mod-proxy-uwsgi
|
|
|
|
You can bind to all external IPs on a non-privileged port using the
|
|
``--http 0.0.0.0:8000`` option. Don't do this when using a reverse proxy
|
|
setup, otherwise it will be possible to bypass the proxy.
|
|
|
|
.. code-block:: text
|
|
|
|
$ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app
|
|
|
|
``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
|
|
IP address in your browser.
|
|
|
|
|
|
Async with gevent
|
|
-----------------
|
|
|
|
The default sync worker is appropriate for many use cases. If you need
|
|
asynchronous support, uWSGI provides a `gevent`_ worker. This is not the
|
|
same as Python's ``async/await``, or the ASGI server spec. You must
|
|
actually use gevent in your own code to see any benefit to using the
|
|
worker.
|
|
|
|
When using gevent, greenlet>=1.0 is required, otherwise context locals
|
|
such as ``request`` will not work as expected. When using PyPy,
|
|
PyPy>=7.3.7 is required.
|
|
|
|
.. code-block:: text
|
|
|
|
$ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app
|
|
|
|
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
|
|
*** Operational MODE: async ***
|
|
mounting hello:app on /
|
|
spawned uWSGI master process (pid: x)
|
|
spawned uWSGI worker 1 (pid: x, cores: 100)
|
|
spawned uWSGI http 1 (pid: x)
|
|
*** running gevent loop engine [addr:x] ***
|
|
|
|
|
|
.. _gevent: https://www.gevent.org/
|