django-downloadview/docs/optimizations/nginx.txt
2013-04-11 15:02:45 +02:00

190 lines
4.8 KiB
Text

#####
Nginx
#####
If you serve Django behind Nginx, then you can delegate the file download
service to Nginx and get increased performance:
* lower resources used by Python/Django workers ;
* faster download.
See `Nginx X-accel documentation`_ for details.
****************************
Configure some download view
****************************
Let's start in the situation described in the :doc:`demo application </demo>`:
* a project "demoproject"
* an application "demoproject.download"
* a :py:class:`django_downloadview.views.ObjectDownloadView` view serves files
of a "Document" model.
We are to make it more efficient with Nginx.
.. note::
Examples below are taken from the :doc:`demo project </demo>`.
***********
Write tests
***********
Use :py:func:`django_downloadview.nginx.assert_x_accel_redirect` function as
a shortcut in your tests.
:file:`demo/demoproject/nginx/tests.py`:
.. literalinclude:: ../../demo/demoproject/nginx/tests.py
:language: python
:emphasize-lines: 5, 25-34
Right now, this test should fail, since you haven't implemented the view yet.
************
Setup Django
************
At the end of this setup, the test should pass, but you still have to `setup
Nginx`_!
You have two options: global setup with a middleware, or per-view setup with
decorators.
Global delegation, with XAccelRedirectMiddleware
================================================
If you want to delegate all file downloads to Nginx, then use
:py:class:`django_downloadview.nginx.XAccelRedirectMiddleware`.
Register it in your settings:
.. code-block:: python
MIDDLEWARE_CLASSES = (
# ...
'django_downloadview.nginx.XAccelRedirectMiddleware',
# ...
)
Setup the middleware:
.. code-block:: python
NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT = MEDIA_ROOT # Could be elsewhere.
NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_URL = '/proxied-download'
Optionally fine-tune the middleware. Default values are ``None``, which means
"use Nginx's defaults".
.. code-block:: python
NGINX_DOWNLOAD_MIDDLEWARE_EXPIRES = False # Force no expiration.
NGINX_DOWNLOAD_MIDDLEWARE_WITH_BUFFERING = False # Force buffering off.
NGINX_DOWNLOAD_MIDDLEWARE_LIMIT_RATE = False # Force limit rate off.
Local delegation, with x_accel_redirect decorator
=================================================
If you want to delegate file downloads to Nginx on a per-view basis, then use
:py:func:`django_downloadview.nginx.x_accel_redirect` decorator.
:file:`demo/demoproject/nginx/views.py`:
.. literalinclude:: ../../demo/demoproject/nginx/views.py
:language: python
And use it in som URL conf, as an example in
:file:`demo/demoproject/nginx/urls.py`:
.. literalinclude:: ../../demo/demoproject/nginx/urls.py
:language: python
.. note::
In real life, you'd certainly want to replace the "download_document" view
instead of registering a new view.
***********
Setup Nginx
***********
See `Nginx X-accel documentation`_ for details.
Here is what you could have in :file:`/etc/nginx/sites-available/default`:
.. code-block:: nginx
charset utf-8;
# Django-powered service.
upstream frontend {
server 127.0.0.1:8000 fail_timeout=0;
}
server {
listen 80 default;
# File-download proxy.
#
# Will serve /var/www/files/myfile.tar.gz when passed URI
# like /optimized-download/myfile.tar.gz
#
# See http://wiki.nginx.org/X-accel
# and https://github.com/benoitbryon/django-downloadview
location /proxied-download {
internal;
# Location to files on disk.
# See Django's settings.NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT
alias /var/www/files/;
}
# Proxy to Django-powered frontend.
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://frontend;
}
}
... where specific configuration is the ``location /optimized-download``
section.
.. note::
``/proxied-download`` is not available for the client, i.e. users
won't be able to download files via ``/optimized-download/<filename>``.
.. warning::
Make sure Nginx can read the files to download! Check permissions.
*************
Common issues
*************
``Unknown charset "utf-8" to override``
=======================================
Add ``charset utf-8;`` in your nginx configuration file.
``open() "path/to/something" failed (2: No such file or directory)``
====================================================================
Check your ``settings.NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT`` in Django
configuration VS ``alias`` in nginx configuration: in a standard configuration,
they should be equal.
.. rubric:: References
.. target-notes::
.. _`Nginx X-accel documentation`: http://wiki.nginx.org/X-accel