Scaling приложения на Python/Django

За более, чем 20 лет существования, Python обзавелся толпой фанатов, большим количеством модулей для всех популярных платформ и множеством Фреймворков. Среди последних заслуженной популярностью пользуется Django, который используется в Instagram, Disqus, Mozilla, Pinterest. Их опыт показывает, что Django справляется с высочайшей нагрузкой и подходит для масштабирования проектов. Django app

С чего начать?

Начинать нужно с профилирования, анализа нагрузки на сервер и проверки веб-приложения на нагрузку. Также ознакомьтесь с принципами построения высоконагруженных приложений и не забудьте провести клиентскую оптимизацию.

Кэширование

После всего вышеперечисленного можно приступать доработке Django-приложения. Начните с кэширования базы данных. Django cache

В Django есть собственный Фреймворк для кэширования. Необходимо создать отдельную таблицу БД для кэша:

python manage.py createcachetable cache_table

# Создает таблицу cache_table

Затем нужно дополнить файл конфигурации settings.py:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'cache_table',
    }
}

# Таким образом легко подключить модуль Memcached для Python

Теперь можно кэшировать нужные данные:

from django.views.decorators.cache import cache_page

@cache_page(60 * 60)
def product_detail(request, product_id):
    ...

# Кэширует страницу на 60 минут (60 секунд * 60 минут)

Система кэширования Django использует полный адрес запроса ("https://www.example.com/stories/2005/?order_by=author") для создания ключей. Но если нужно выдавать разный контент в зависимости от куки, языка, агента пользователя, фреймворк умеет варьировать отдачу при помощи заголовков Vary:

from django.views.decorators.vary import vary_on_headers

@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
    ...

# Система создаст отдельные кэши для разных пользователей

Не забывайте, что можно кэшировать страницы с динамическим контентом. Используйте уловки. Новые комментарии не обязательно показывать в момент их публикации, задержка отображения в несколько минут некритична. Учтите, что даже кэширование на 10 секунд уменьшит нагрузку на всю систему. Для улучшения общей производительности веб-проекта можно использовать кэширование с ESI, Varnish, также пригодится Memcache.

Управление статическим контентом

В большинстве случаев Django лучше не использовать для раздачи статики (кроме данных авторизации). Но фреймворк удобно использовать для управления статическими файлами, который затем будут отдаваться веб-сервером.

Для начала необходимо отредактировать файл конфигурации settings.py:

STATIC_ROOT = os.path.join(BASE_DIR, "static")

# Определяет, что статические файлы будут храниться в основной директории веб-приложения

После можно запускать сборщик статики:

python manage.py collectstatic

# Собирает статические файлы в указанную директорию

Когда Python завершит процесс сборки, в главной директории приложения появится каталог static, в котором будут собраны все файлы (CSS, JS, картинки и т.д.), разобранные по подкаталогам.

Осталось указать, в каких каталогах лежат эти файлы:

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

# Указание каталога со статикой в файле настроек settings.py

А еще лучше указать путь в настройках веб-сервера, который выполнит работу быстрее, чем Django. Для Nginx нужно добавить:

server {
    ...
    location /static/ {
        alias /srv/testapp/static/;
    }
}

# Таких каталогов может быть несколько и для разных категорий приложения

uWSGI

WSGI — протокол взаимодействия Python с веб-сервером. А uWSGI — современная реализация протокола. То есть пользователь отправляет запрос веб-серверу, тот в свою очередь через uWSGI передает его на Django-приложение и получает ответ. Django uWSGI

При помощи uWSGI можно ограничивать количество запущенных процессов приложения, обычно выполняется один родительский процесс и два воркера. При необходимости можно увеличить количество воркеров, или уменьшить их число.

Настройка и включение

uWSGI позволит приложению Django и Nginx общаться. Для начала его нужно установить:

sudo aptitude install uswgi

# Установка через системные пакеты

Модуль также можно установить через pip или собрать из исходников.

После установки появится две новых директории: /etc/uwsgi/apps-available и /etc/uwsgi/apps-enabled. Схема работы простая, для работы приложения необходимо его файл настроек положить в apps-available и ссылаться на него в apps-enabled.

Сам файл настроек проекта testapp.ini будет иметь вид:

[uwsgi]
touch-reload = /tmp/testapp
socket = 127.0.0.1:9001
workers = 2
chdir = /srv/testapp
env = DJANGO_SETTINGS_MODULE=testapp.settings
module = django.core.handlers.wsgi:WSGIHander()

# Указывает сокет и количество воркеров

Осталось создать пустой файл, указанный в touch-reload:

touch /tmp/testapp

# uWSGI будет перезагружаться при изменении файла

И связать проекты:

sudo ln -s /etc/uwsgi/apps-available/testapp.ini /etc/uwsgi/apps-enabled/testapp.ini

# Не забудьте указать собственные пути

Теперь нужно перезагрузить uWSGI и сконфигурировать веб-сервер.

Настройка Nginx

Веб-сервер нужно пересобрать, добавив модуль ngx_http_uwsgi_module. Затем нужно создать файл конфигурации для веб-приложения /etc/nginx/sites-available/testapp, который будет похож на:

server {
        listen          80;
        server_name     $hostname;
        access_log /srv/testapp/logs/access.log;
        error_log /srv/testapp/logs/error.log;

        location / {
            uwsgi_pass      127.0.0.1:9001;
            include         uwsgi_params;
            uwsgi_param     UWSGI_SCHEME $scheme;
            
        }

        location /static {
            alias /srv/testapp/static/;
            index  index.html index.htm;

        }
}

# С указанием сокета и адреса со статическими файлами

Также можно настроить кластер, используя Nginx в качестве балансировщика:

upstream uwsgicluster {
     server 127.0.0.1:9001;
     server 192.168.100.101:9001;
     server 192.168.100.102:9001;
     server 192.168.100.103:9001;
     server 192.168.100.104:9001;
}

# Nginx будет распределять нагрузку равномерно

Самое главное

Кэширование и модуль uWSGI способны повысить производительность и скорость веб-приложения Django. Такая архитектура легко масштабируется и не требует дополнительных вложений. Не забывайте оптимизировать настройки веб-сервера для повышения отзывчивости сайта.


Подпишитесь на Хайлоад с помощью Google аккаунта
или закройте эту хрень