Масштабирование Django: продвинутые решения

Теперь вы знаете, как искать узкие места и устранять базовые проблемы производительности. Этого хватит на первое время, но в дальнейшем приложение станет получать еще больше трафика. Как же справиться с такими объемами данных?

Нужно немного разобраться в настройках приложения и конфигурации сервера.

Примечание: Данный мануал написан для Ubuntu 12.04, но подойдет для любого дистрибутива Linux. Если вы используете Apache, вы можете оптимизировать свой веб-сервер.

1: Кэширование

Если вы настроили CMS для управления сайтом, вы, вероятно, без проблем сможете выполнить кэширование большого количества данных. Для этого рекомендуем использовать Varnish. Чтобы установить Varnish, обратитесь к этим мануалам:

У Varnish есть один недостаток: без тщательной настройки он кэширует весь ваш сайт. Если у вас есть динамический контент (это особенно важно для приложений), Varnish может вызвать множество проблем. Представьте, что пользователь A посещает сайт и добавляет элемент в свою корзину покупок. Затем пользователь B посещает сайт и видит кэшированную версию корзины покупок с элементом пользователя A. Таких нехороших ситуаций нужно избегать.

Еще одним недостатком является то, что Django по умолчанию пытается кэшировать апстрим, а не контент, что приводит к конфликтам и неустойчивому поведению.

Но у Django есть свой собственный фреймворк кеширования, который имеет два преимущества:

  • Он делает приложение более дружественным к кэшированию Varnish.
  • Он предоставляет контроль над кешированием сайта.

На небольшом сервере можно кэшировать БД. Эта процедура проста и не требует дополнительных процессов на сервере. Если у вас достаточно RAM, вы можете использовать для кэширования memcached.

Читайте также: Установка и использование Memcache на Ubuntu 12.04

В БД создайте таблицу для кэша, например:

python manage.py createcachetable cache_table

Отредактируйте файл settings.py и настройте кэширование при помощи этих параметров:

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

Вы также можете настроить дополнительные параметры конфигурации. Читайте о них в документации; особое внимание уделите параметрам TIMEOUT и CULL_FREQUENCY.

Теперь вам нужно решить, что кэшировать. Если вы просто хотите оптимизировать работу сайта с помощью Varnish, проверьте конфигурацию кэша сайта.

Давайте рассмотрим подробнее кэширование по просмотрам. Допустим, у вас на сайте есть корзина, которая редко меняется и не динамична. У вас есть представление под названием product_detail (request, product_id), которое идеально подходит для кэширования.

Чтобы включить кэширование этой страницы, используйте:

from django.views.decorators.cache import cache_page
@cache_page(60 * 60)
def product_detail(request, product_id):
...

Это позволит кэшировать это представление в течение 60 минут (60 секунд * 60 минут).

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

Кэширование контента, который часто меняется

Если у вас есть полудинамический сайт (например, ваше приложение получает много комментариев или данные часто обновляются), кэширование может вызвать проблемы.

Во-первых, определите все представления, которые можно кэшировать, а затем кэшируйте их.

Во-вторых, укажите, как долго пользователь может видеть устаревший контент. Например, сайт с активными комментариями, вероятно, может переносить задержку от 1 до 5 минут. Кэшируйте страницы настолько долго, насколько это возможно.

Удивительно, но даже десятисекундный кэш может оказаться очень полезным. Во многих случаях перенагрузки на загруженных сайтах основной поток трафика идет на определенную страницу.

Если 10 000 человек посетят страницу сайта в течение минуты, она перенагрузит сервер, так как все эти запросы будут одновременно передаваться в базу данных. Если вы установите кэш в 10 секунд, то страница будет обновляться только 6 раз в минуту, независимо от того, сколько людей ее запрашивает. Любой сервер может обработать такую нагрузку.

Сайты электронной коммерции и сайты, использующие данные сеанса, должны быть очень осторожными. Ознакомьтесь с опцией vary и рассмотрите ее использование в кэшировании.

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

2: Обслуживание статического контента

Встроенный сервер разработки Django быстро обслуживает статический контент. Зачастую сайты Django в производстве используют статический контент, который обслуживается Django.

Делать это нужно только тогда, когда вам нужно контролировать доступ к контенту. Но даже в таком случае рассмотрите другие способы.

Ознакомьтесь с документацией по статическим файлам.

Если у вас нет своих вариантов, вы можете использовать следующий сценарий.

На локальной машине разработки в разделе settings.py добавьте следующую строку:

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

Затем запустите команду manage.py:

python manage.py collectstatic

Теперь в корневом каталоге проекта появится каталог static, в котором вы увидите много статических файлов, таких как CSS и Javascript.

Чтобы использовать эти файлы, вам нужно указать Django, где их искать. В каталоге settings.py вам понадобится такая опция:

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

Теперь, если вы запустите сервер разработки, зайдите в область администратора и просмотрите исходный код любой страницы, вы увидите, что файлы CSS обслуживаются из /static/admin/css/.

При развертывании приложения вы можете настроить Apache или Nginx для работы с файлами, которые начинаются с /static/, направив их непосредственно на файлы.

Если приложение развернуто в /srv/myapp/ и у вас есть файл /srv/myapp/static/admin/css/base.css, тогда вы можете настроить веб-сервер так:

Apache:
Alias /static/ "/srv/myapp/static/"
Nginx:
server {
...
location /static/ {
alias /srv/myapp/static/;
}
}

В обоих случаях вы просто направляете /static/ URL на точное место на жестком диске, где находятся файлы. Apache и Nginx могут обслуживать их гораздо быстрее, чем Django.

3: Использование uWSGI

Чтобы быстро запустить сайт, можно использовать модуль Apache mod_wsgi. Чтобы оптимизировать производительность сайта, можно использовать uWSGI.

uWSGI – это серверный процесс, который запускает приложение вне веб-сервера. Для Apache необходимо установить эти пакеты:

sudo apt-get install uwsgi uwsgi-plugin-python uwsgi-plugin-cgi

Также веб-серверу Apache нужны следующие пакеты:

sudo apt-get install libapache2-mod-uwsgi

после этого у вас появятся новые каталоги для конфигураций: /etc/uwsgi/apps-available и /etc/uwsgi/apps-enabled (работают аналогично каталогам для виртуальных хостов Apache или Nginx).

Когда вы хотите создать новое приложение, вы помещаете конфигурационный файл в /etc/uwsgi/apps-available, а затем создаете символическую ссылку на него из приложений.

Предположим, у вас есть проект newproject, который нужно поместить в /srv/newproject. Также у проекта есть файл settings.py в /srv/newproject/newproject/settings.py, что типично для проектов Django.

Создайте файл `/etc/uwsgi/apps-available/newproject.ini и отредактируйте его так:

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

Затем создайте пустой файл /tmp/newproject:

touch /tmp/newproject

Включите приложение, создав ссылку на файл в apps-enabled:

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

Перезапустите uWSGI:

sudo service uwsgi restart

Если вы проверите вывод ps a», вы увидите несколько процессов, связанных с приложением.

Обратите внимание: если на одном сервере работает несколько приложений, вам необходимо использовать другой порт для каждого сокета приложения.

Кроме того, при обновлении приложения нужно выполнить touch для файла /tmp/newproject, и uWSGI перезагрузится.

В любое время вы можете открыть /var/log/uwsgi/app/newproject.log, чтобы просмотреть системные сообщения и ошибки.

4: Настройка Apache

Если вы используете mod_wsgi, отключите его и включите вместо него mod_uwsgi. Это может вызвать ошибки, так что сначала сделайте это на тестовом сервере. Найдя правильную конфигурацию, вы сможете перенести ее в производство.

sudo a2dismod wsgi
sudo a2enmod uwsgi

затем обновите конфигурации приложения. В конфигурационном файле Apache вы найдете такую строку:

WSGIScriptAlias / /srv/newproject/newproject.wsgi

Обновите ее таким образом:

SetHandler uwsgi-handler
uWSGISocket 127.0.0.1:3031

Перезапустите Apache:

sudo service apache2 reload

5: Настройка Nginx

В конфигурациях сервера замените директивы wsgi:

uwsgi_pass      127.0.0.1:3031;
include         uwsgi_params;
uwsgi_param     UWSGI_SCHEME $scheme;

6: Преимущества uWSGI

Одним из преимуществ использования uWSGI является то, что вы можете ограничить количество запусков приложения в памяти. Обычно используется один родительский процесс и два рабочих процесса. Если вам нужно больше рабочих процессов, вы можете просто отредактировать файл .ini для приложения и увеличить количество рабочих процессов. Затем перезагрузите uWSGI с помощью команды:

sudo service uwsgi reload

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

7: Использование памяти

После того как ваше приложение какое-то время поработает, просмотрите использование памяти вашего сервера.

Используйте команду free -m, чтобы узнать, сколько памяти используется буферами, кэшем и приложениями. Ключевым значением является верхнее число в столбце free. В идеале загруженный сервер будет использовать почти всю оперативную память.

Если вы обнаружите, что у вас есть свободная оперативная память, а ваш сайт работает медленно, проанализируйте ситуацию и попробуйте оптимизировать использование памяти.

Часто оперативная память нужна MySQL. Возможно, нужно выделить больше системной памяти для базы данных. Это чрезвычайно распространенная ситуация, потому что конфигурация по умолчанию для MySQL использует RAM очень экономно.

Также оперативная память, возможно, нужна дисковому кэшу. У вас есть ненужные процессы, занимающие память? По умолчанию Linux будет выделять на дисковый кэш максимально доступное количество оперативной памяти.

В идеальной ситуации (которая никогда не встречается в среде VPS с ограниченным объемом памяти) все ресурсы только для чтения будут буферизованы в кэше. Поэтому избавитесь от ненужных фоновых процессов.

Заключение

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

Tags: , , ,